通过Boost ASIO服务器发送缓冲区 - 发送错误的数据

时间:2016-02-03 07:55:20

标签: c++ arrays boost server boost-asio

有谁能告诉我如何将存储在数组中的十六进制值不变地发送到客户端??

每当我通过boost服务器向客户端发送一个十六进制char数组时,它会将其转换为ASCII / JUNK(不能决定它是什么)。

Ex的

我正在尝试发送

"24 bb ff 0f 02 08 01 e0 01 e0 02 08 0f 2d 0f 00 23 61"
通过Boost asio服务器在char数组中

修改

客户正在接收

"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"

这是我正在使用的一段代码。

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));

我应该使用不同的缓冲区或任何其他方式发送十六进制值???

2 个答案:

答案 0 :(得分:1)

如果代码尝试发送超过37个字节,那么它将发送未初始化的内存。如果它尝试发送超过512个字节,则它正在读取超出缓冲区的末尾。在任何一种情况下,都可能会发送内存垃圾邮件模式。

Sendingdata_缓冲区为512字节,但这些字节中只有37个已初始化。

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), ...);

正在为finalHex字符串提供字符串文字。例如,为字符串升级"2400bb"分配字符串,将存储'2''4''0''0''b',和'b' ASCII字符。

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]);

考虑使用向量,以十六进制表示法提供数值:

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

或者,通过提供std::string控制字符来指示后续值为十六进制,可以使用\x。但是,在解释值时可能需要执行显式转换,并使用处理字符串中的空字符的构造函数:

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]));

以下是demonstrating差异和Asio缓冲区用法的示例:

#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]));
}

答案 1 :(得分:0)

因为您正在发送一个众所周知的内存垃圾邮件模式(often used: 0xDEADBEEF, 0xBAADF00D, etc.),我假设您正在读取缓冲区的末尾,或者您可能正在取消引用过时的指针。

我看到人们使用ASIO做出的一个常见错误是:

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

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

问题是使用带有异步调用的stacklocal缓冲区。 async_write将立即返回,foo将返回。在异步操作访问它之前,packet可能已经消失。

如果您正在运行调试堆库,这是导致您读取垃圾邮件模式而不是缓冲区内容的原因之一。