boost::asio async_write也不能保证一次发完所有数据 二

简介: 只有看boost源码才能弄明白发生了什么。首先我是将vector里面写入了数据,然后用boost::asio::buffer将vector构造成了mutable_buffer_1对象。 参考该文档的重载形式:http://www.

只有看boost源码才能弄明白发生了什么。首先我是将vector里面写入了数据,然后用boost::asio::buffer将vector构造成了mutable_buffer_1对象。

参考该文档的重载形式:http://www.boost.org/doc/libs/1_53_0/doc/html/boost_asio/reference/buffer/overload24.html

 

[cpp]  view plain copy print ?
 
  1. buffer (24 of 28 overloads)  
  2.   
  3. Create a new modifiable buffer that represents the given POD vector.  
  4.   
  5. template<  
  6.     typename PodType,  
  7.     typename Allocator>  
  8. mutable_buffers_1 buffer(  
  9.     std::vector< PodType, Allocator > & data,  
  10.     std::size_t max_size_in_bytes);  
  11. Return Value  
  12.   
  13. A mutable_buffers_1 value equivalent to:  
  14.   
  15. mutable_buffers_1(  
  16.     data.size() ? &data[0] : 0,  
  17.     min(data.size() * sizeof(PodType), max_size_in_bytes));  


注意,上面的代码最后一部分就是解释了内部原理。原来是调用vector的size成员函数,然后和传入的size比较,谁小用谁。会不会是我的vector::size返回的不是54,而是9呢。

 

很快我加上日志追踪,果然是9. 为什么呢? 这肯定和我对vector写数据的操作有关。下面是代码片段:

 

[cpp]  view plain copy print ?
 
  1. void ConfigMessage::Write(vector<char>& buffer) {  
  2.   buffer.assign(9, 0);  
  3.   // SOH  
  4.   buffer[0] = 0x01;  
  5.   
  6.   // Type  
  7.   size_t i = 3;  
  8.   buffer[i++] = 'U';  
  9.   buffer[i++] = '1';  
  10.     
  11.   size_t len = domain.length();  
  12.   buffer[i++] = static_cast<uint8_t>(len);  
  13.   memcpy(&buffer[i], domain.c_str(), len);  
  14.   i += len;  
  15.   
  16.   uint16_t temp = Int16ToBigEndian<uint16_t>(port);  
  17.   memcpy(&buffer[i], &temp, 2);  
  18.   i += 2;  
  19.   
  20.   buffer[i++] = timezone;  


我基本上当作一个C的缓冲区在用memcpy来填入数据,因此vector的size成员不能正确反映实际的数据。因此我在最后加上一个调用:

 

 

[cpp]  view plain copy print ?
 
  1. buffer.resize(size_);  


再测试。问题解决。

 

 

所以,当用vector构造buffer时要小心他的最小规则。这个问题是我自己的逻辑造成的。‘

不过在之前的那篇文章中写的递归保护代码也有保险作用。万一哪天自己又犯了错误,至少它能保证数据全部发完。

目录
相关文章
|
5月前
|
存储
19.7 Boost Asio 传输序列化数据
序列化和反序列化是指将数据结构或对象转换为一组字节,以便在需要时可以将其存储在磁盘上或通过网络传输,并且可以在需要时重新创建原始对象或数据结构。 序列化是将内存中的对象转换为字节的过程。在序列化期间,对象的状态被编码为一组字节,并可以保存或传输到另一个位置。序列化后的字节可以在之后进行反序列化,以将对象重建为在序列化之前的状态。反序列化则是将字节序列重新转换为对象或数据结构的过程。在反序列化期间,字节被反转回原始对象的状态,以便它可以被使用或操作。
32 0
19.7 Boost Asio 传输序列化数据
|
5月前
19.10 Boost Asio 同步文件传输
在原生套接字编程中我们介绍了利用文件长度来控制文件传输的方法,本节我们将采用另一种传输方式,我们通过判断字符串是否包含`goodbye lyshark`关键词来验证文件是否传输结束了,当然了这种传输方式明显没有根据长度传输严谨,但使用这种方式也存在一个有点,那就是无需确定文件长度,因为无需读入文件所以在传输速度上要快一些,尤其是面对大文件时。服务端代码如下所示,在代码中我们分别封装实现`recv_remote_file`该函数用于将远程特定目录下的文件拉取到本地目录下,而`send_local_file`函数则用于将一个本地文件传输到对端主机上,这两个函数都接收三个参数,分别是套接字句柄,本地
54 0
19.10 Boost Asio 同步文件传输
|
5月前
19.3 Boost Asio 多线程通信
多线程服务依赖于两个通用函数,首先`boost::bind`提供了一个高效的、简单的方法来创建函数对象和函数对象适配器,它的主要功能是提供了一种将函数和它的参数绑定到一起的方法,这种方法可以将具有参数的成员函数、普通函数以及函数对象转化为不带参数的函数对象。当参数绑定后则下一步就需要使用多线程功能,Boost库中提供了`boost::thread`库,`boost::thread`可以用于创建线程、启动线程、等待线程执行结束以及线程间通信等多种操,有了这两个关键库那么我们只需要`accept.accept(*sock)`等待套接字上线,当有套接字上线后则自动创建`MyThread`子线程,
47 0
19.3 Boost Asio 多线程通信
|
3月前
boost asio多线程
boost asio多线程
|
5月前
|
Python
19.9 Boost Asio 同步字典传输
这里所代指的字典是Python中的样子,本节内容我们将通过使用Boost中自带的`Tokenizer`分词器实现对特定字符串的切割功能,使用Boost Tokenizer,可以通过构建一个分隔符或正则表达式的实例来初始化`tokenizer`。然后,可以使用该实例对输入字符串进行划分。`tokenizer`将在输入字符串中寻找匹配输入模式的标记,并将其拆分为单独的字符串。
22 0
19.9 Boost Asio 同步字典传输
|
5月前
19.5 Boost Asio 传输结构体
同步模式下的结构体传输与原生套接字实现方式完全一致,读者需要注意的是在接收参数是应该使用`socket.read_some`函数读取,发送参数则使用`socket.write_some`函数实现,对于套接字的解析同样使用强制指针转换的方法。
29 0
19.5 Boost Asio 传输结构体
boost::asio::read_until数据获取重复问题
利用boost::asio::read_until读http的chunk包,读取部分代码如下: 第一部分读取包头,第二部分循环读chunk包 如果不调用consume清空的话,while循环里一直获取到的是包头部分的内容...
1562 0
|
移动开发 网络协议 流计算