Jithendra
Jithendra

Reputation: 351

Sending buffer via Boost ASIO server - sending the wrong data

Can anyone tell me how to send hexadecimal values stored in array unchanged to client??

whenever I send a char array of hexadecimal to client via boost server, its converting it to ASCII/JUNK(Can't decide what it is).

for Ex:

I am trying to send

"24 bb ff 0f 02 08 01 e0 01 e0 02 08 0f 2d 0f 00 23 61"

in char array via Boost asio server.

Edit:

Client is receiving

"32 34 62 62 66 66 30 66 30 32 30 38 30 31 65 30 30 31 65 30 30 32 30 38 30 66 32 64 30 66 30 30 32 33 36 31"

this is the piece of code I am using.

char Sendingdata_[512];
string finalHex = "24bbff0f020801e001e002080f2d0f002361";
strcpy(Sendingdata_, finalHex.c_str());
boost::asio::async_write(socket_, boost::asio::buffer(Sendingdata_,bytes_transferred), boost::bind(&session::handle_write, this, boost::asio::placeholders::error));

should I use different buffers or any other way to send hexadecimal values???

Upvotes: 1

Views: 1744

Answers (2)

Tanner Sansbury
Tanner Sansbury

Reputation: 51951

If the code is attempting to send more than 37 bytes, then it will be sending uninitialized memory. If it is attempting to send more than 512 bytes, then it is reading beyond the end of the buffer. In either case, memory trash patterns may be sent.

The Sendingdata_ buffer is 512 bytes, but only 37 of those bytes have been initialized.

char Sendingdata_[512];                 // 512 unitialized values.
std::string finalHex = string-literal;  // 36 ASCII characters + null termination.
strcpy(Sendingdata_, finalHex.c_str()); // 37 characters copied
boost::asio::async_write(..., boost::asio::buffer(Sendingdata_, bytes_transferred), ...);

The finalHex string is being provided a string literal. For example, assigning a string the string-literial of "2400bb", will store the '2', '4', '0', '0', 'b', and 'b' ASCII characters.

std::string ascii = "2400bb";
assert(ascii.length() == 6);
assert('2' == ascii[0]);
assert('4' == ascii[1]);
assert('0' == ascii[2]);
assert('0' == ascii[3]);
assert('b' == ascii[4]);
assert('b' == ascii[5]);

Consider using a vector, providing the numeric value in hex notation:

std::vector<unsigned char> hex = { 0x24, 0x00, 0xbb };
assert(hex.size() == 3);
assert(0x24 == hex[0]);
assert(0x00 == hex[1]);
assert(0xbb == hex[2]);

Alternatively, one could use std::string by providing the \x control character to indicate that the subsequent value is hex. However, one may need to perform explicit casting when interpreting the values, and use constructors that handle the null character within the string:

std::string hex("\x24\x00\xbb", 3);
// alternatively: std::string hex{ 0x24, 0x00, static_cast<char>(0xbb) };  
assert(hex.size() == 3);
assert(0x24 == static_cast<unsigned char>(hex[0]));
assert(0x00 == static_cast<unsigned char>(hex[1]));
assert(0xbb == static_cast<unsigned char>(hex[2]));

Here is an example demonstrating the differences and Asio buffer usage:

#include <cassert>
#include <functional>
#include <iostream>
#include <string>
#include <vector>
#include <boost/asio.hpp>

int main()
{
  // String-literial.
  std::string ascii = "2400bb";
  assert(ascii.length() == 6);
  assert('2' == ascii[0]);
  assert('4' == ascii[1]);
  assert('0' == ascii[2]);
  assert('0' == ascii[3]);
  assert('b' == ascii[4]);
  assert('b' == ascii[5]);

  // Verify asio buffers.
  auto ascii_buffer = boost::asio::buffer(ascii);
  assert(ascii.length() == boost::asio::buffer_size(ascii_buffer));
  assert(std::equal(
    boost::asio::buffers_begin(ascii_buffer),
    boost::asio::buffers_end(ascii_buffer),
    std::begin(ascii)));

  // Hex values.
  std::vector<unsigned char> hex = { 0x24, 0x00, 0xbb };
  // alternatively: unsigned char hex[] = { 0x24, 0x00, 0xbb };
  assert(hex.size() == 3);
  assert(0x24 == hex[0]);
  assert(0x00 == hex[1]);
  assert(0xbb == hex[2]);

  // Verify asio buffers.
  auto hex_buffer = boost::asio::buffer(hex);
  assert(hex.size() == boost::asio::buffer_size(hex_buffer));
  assert(std::equal(
    boost::asio::buffers_begin(hex_buffer),
    boost::asio::buffers_end(hex_buffer),
    std::begin(hex),
    std::equal_to<unsigned char>()));

  // String with hex.  As 0x00 is in the string, the string(char*) constructor
  // cannot be used.
  std::string hex2("\x24\x00\xbb", 3);
  // alternatively: std::string hex2{ 0x24, 0x00, static_cast<char>(0xbb) };  
  assert(hex2.size() == 3);
  assert(0x24 == static_cast<unsigned char>(hex2[0]));
  assert(0x00 == static_cast<unsigned char>(hex2[1]));
  assert(0xbb == static_cast<unsigned char>(hex2[2]));
}

Upvotes: 1

sehe
sehe

Reputation: 393583

Because you're sending a wellknown memory trash pattern (often used: 0xDEADBEEF, 0xBAADF00D, etc.) I'd assume you're reading past the end of a buffer, or perhaps you're dereferencing a stale pointer.

One of the common errors I see people make with ASIO is this:

void foo() {
     std::string packet = "hello world";

     boost::asio::async_write(socket_, asio::buffer(packet), my_callback);
}

The problem is using a stacklocal buffer with an asynchronous call. async_write will return immediately, foo will return. packet is probably gone before the asynchronous operation accesses it.

This is one of the reasons that could lead to you reading the trash pattern instead of your buffer contents, if you're running a debug heap library.

Upvotes: 1

Related Questions