简体   繁体   English

提升Asio跨平台换行符的困惑

[英]boost asio cross platform newline confusion

I am using boost asio to write simple server/client to transmit binary data. 我正在使用boost asio编写简单的服务器/客户端来传输二进制数据。 Particularly, I am using async_write and async_read with ip:tcp::socket. 特别是,我在ip:tcp :: socket中使用async_write和async_read。 Nothing fancy, really. 没什么,真的。

boost::asio::async_write(*mp_socket, boost::asio::buffer(data_ptr, data_size), 
                         boost::bind(&TcpSocket::m_handleWrite, this,
                                     boost::asio::placeholders::error,
                                     boost::asio::placeholders::bytes_transferred));

boost::asio::async_read(*mp_socket, boost::asio::buffer(mp_buffer, m_buffer_size),
                         boost::bind(&TcpSocket::m_handleRead, this,
                                     boost::asio::placeholders::error,
                                     boost::asio::placeholders::bytes_transferred));

I randomly generated binary data and send/receive in various platform pairs to test. 我随机生成二进制数据,并在各种平台对中进行发送/接收以进行测试。 The code works fine in same platform (such as all in linux, all in windows), but fails to work cross platform. 该代码在同一平台上可以正常工作(例如在Linux中所有,在Windows中所有),但是无法在跨平台上工作。

For example, the left is received data in windows, and the right is sent data in linux. 例如,左边是在Windows中接收的数据,右边是在Linux中发送的数据。 The only difference is 0D0A (CRLF) in windows and 0A (LF) in linux. 唯一的区别是Windows中的0D0A(CRLF)和Linux中的0A(LF)。 I think somewhere (in boost asio, or in winsock, or etc..), LF->CRLF conversion is happening. 我认为某个地方(在Boost asio或winsock等中),正在发生LF-> CRLF转换。

So, is there a way to disable the conversion, as I am sending binary data? 因此,在发送二进制数据时,有没有办法禁用转换? I was looking for some option in boost::asio configuration (such as using raw buffer, not stream buffer), but could not find it. 我在boost :: asio配置中寻找某些选项(例如使用原始缓冲区,而不是流缓冲区),但找不到它。 Thank you for the help. 感谢您的帮助。

在此处输入图片说明


data in data_ptr data_ptr中的数据

  size_t sz = rand() % 60000;
  char* p = (char*)malloc(sz + 4);
  uint32_t* p_header = reinterpret_cast<uint32_t*>(p);
  *p_header = htonl((uint32_t)sz);
  for (size_t i = 0; i < sz; ++i)
  {
    p[i + 4] = rand() % 255;
  }

I think that the issue is because async_read is "stream-oriented", see: Short reads and writes . 我认为问题是因为async_read是“面向流的”,请参阅: 短读写

I assume that asio is using CRLF or LF as the stream terminators in Windows and Linux respectively and I guess that somewhere it's using a Windows terminator for a Linux stream or vice-versa. 我假设asio分别在Windows和Linux中使用CRLFLF作为流终结器,并且我猜想它在某处使用Windows终结器进行Linux流,反之亦然。

Try changing your async_read call to: 尝试将您的async_read调用更改为:

mp_socket->async_read_some(boost::asio::buffer(mp_buffer, m_buffer_size),
                           boost::bind(&TcpSocket::m_handleRead, this,
                                       boost::asio::placeholders::error,
                                       boost::asio::placeholders::bytes_transferred));

I've used this method to read large binary files and verified the received files against their hash without any of the problems that you've encountered. 我已经使用这种方法读取大型二进制文件,并对照它们的哈希值验证了接收到的文件,而没有遇到任何问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM