(原创)谈谈boost.asio的异步发送
在上一篇博文中提到asio的异步发送稍微复杂一点,有必要单独拿出来说说。asio异步发送复杂的地方在于: 不能连续调用异步发送接口async_write,因为async_write内部是不断调用async_write_some,直到所有的数据发送完成为止。由于async_write调用之后就直接返回了,如果第一次调用async_write发送一个较大的包时,马上又再调用async_write发送一个很小的包时,有可能这时第一次的async_write还在循环调用async_write_some发送,而第二次的async_write要发送的数据很小,一下子就发出去了,这使得第一次发送的数据和第二次发送的数据交织在一起了,导致发送乱序的问题。解决这个问题的方法就是在第一次发送完成之后再发送第二次的数据。具体的做法是用一个发送缓冲区,在异步发送完成之后从缓冲区再取下一个数据包发送。下面看看异步发送的代码是如何实现的。
list<MyMessage> m_sendQueue; //发送队列 void HandleAsyncWrite(char* data, int len)
{
bool write_in_progress = !m_sendQueue.empty();
m_sendQueue.emplace_back(data, len);
if (!write_in_progress)
{
AsyncWrite();
}
} void AsyncWrite()
{
auto msg = m_sendQueue.front();
async_write(m_sock, buffer(msg.pData, msg.len),
[this](const boost::system::error_code& ec, std::size_t size)
{
if (!ec)
{
m_sendQueue.pop_front(); if (!m_sendQueue.empty())
{
AsyncWrite();
}
}
else
{
HandleError(ec);
if (!m_sendQueue.empty())
m_sendQueue.clear();
}
});
}
代码的逻辑是这样的:当用户发送数据时,不直接调用异步发送接口,而是将数据放到一个发送队列中,异步发送接口会循环从队列中取数据发送。循环发送过程的一个细节需要注意,用户发送数据时,如果发送队列为空时,说明异步发送已经将队列中所有的数据都发送完了,也意味着循环发送结束了,这时,需要在数据入队列之后再调用一下async_write重新发起异步循环发送。
可以看到,异步发送比异步接收等其他异步操作更复杂,需要一个发送队列来保证发送不会乱序。但是,还有一个问题需要注意就是这个发送队列是没有加限制的,如果接收端收到数据之后阻塞处理,而发送又很快的话,就会导致发送队列的内存快速增长甚至内存爆掉。解决办法有两个:
- 发慢一点,并且保证接收端不会长时间阻塞socket;
- 控制发送队列的上限。
第一种方法对实际应用的约束性较强,实际可操作性不高。第二种方法需要控制队列上限,不可避免的要加锁,这样就丧失了单线程异步发送的性能优势。所以建议用同步发送接口来发送数据,一来不用发送队列,自然也不会有内存暴涨的问题,二来也不会有复杂的循环发送过程,而且还可以通过线程池来提高发送效率。
总结:
- 不要连续发起异步发送,要等上次发送完成之后再发起下一个异步发送;
- 要考虑异步发送的发送队列内存可能会暴涨的问题;
- 相比复杂的异步发送,同步发送简单可靠,推荐优先使用同步发送接口。
如果你觉得这篇文章对你有用,可以点一下推荐,谢谢。
c++11 boost技术交流群:296561497,欢迎大家来交流技术。
(原创)谈谈boost.asio的异步发送的更多相关文章
- boost::asio 同步&异步例子
同步客户端: using boost::asio; io_service service; ip::tcp::endpoint ep( ip::address::from_string(); ip:: ...
- 使用Boost asio实现异步的TCP/IP通信
可以先了解一下Boost asio基本概念,以下是Boost asio实现的异步TCP/IP通信: 服务器: #include "stdafx.h" #include <io ...
- boost Asio网络编程简介
:first-child { margin-top: 0px; } .markdown-preview:not([data-use-github-style]) h1, .markdown-previ ...
- Boost.Asio的使用技巧
基本概念 Asio proactor I/O服务 work类 run() vs poll() stop() post() vs dispatch() buffer类 缓冲区管理 I/O对象 socke ...
- boost.asio源码剖析(三) ---- 流程分析
* 常见流程分析之一(Tcp异步连接) 我们用一个简单的demo分析Tcp异步连接的流程: #include <iostream> #include <boost/asio.hpp& ...
- Boost Asio介绍--之一
原文:http://www.tuicool.com/articles/YbeYR3 Boost Asio介绍--之一 时间 2014-03-26 17:57:39 CSDN博客 原文 http:/ ...
- Boost Asio(一)初探
一.简介 Boost Asio ( asynchronous input and output)关注数据的异步输入输出.Boost Asio 库提供了平台无关性的异步数据处理能力(当然它也支持同步数据 ...
- boost::asio 的同、异步方式
转自:http://blog.csdn.net/zhuky/archive/2010/03/10/5364574.aspx Boost.Asio是一个跨平台的网络及底层IO的C++编程库,它使用现代C ...
- Boost.Asio基础(五) 异步编程初探
异步编程 本节深入讨论异步编程将遇到的若干问题.建议多次阅读,以便吃透这一节的内容,这一节是对整个boost.asio来说是非常重要的. 为什么须要异步 如前所述,通常同步编程要比异步编程更简单.同步 ...
随机推荐
- hdu 4122 Alice's mooncake shop (线段树)
题目大意: 一个月饼店每一个小时做出月饼的花费不一样. 储存起来要钱.最多存多久.问你把全部订单做完的最少花费. 思路分析: ans = segma( num[]*(cost[] + (i-j)*s) ...
- 查看tcp连接信息socket几个常用的命令
查看tcp连接几个常用的命令 1 ss ss 列出所有的连接,包括tcp连接.udp连接.unix socket.raw socket ss -t 列出所有tcp连接 ss -tl 列出所有处于监听状 ...
- 对Java的常用对象(POJO、DTO、PO、BO、VO、DAO)详细解释及应用场景
首先这些对象都应用都是一些单词的简称,也是一种应用思想,故其他语言也可以使用,在Java里比较常见这些对象吧.下面来一一解释. 一.POJO(Plain Ordinary Java Object). ...
- 运维自动化之Cobbler系统安装使用详解[good]
一.简介 Cobbler是一个快速网络安装linux的服务,而且在经过调整也可以支持网络安装windows.该工具使用python开发,小巧轻便(才15k行python代码),使用简单的命令即可完成P ...
- Linux-非结构化数据同步-Linux下Rsync+Rsync实现非结构化增量差异数据的同步2
说明: 操作系统:CentOS 5.X 源服务器:192.168.21.129 目标服务器:192.168.21.127,192.168.21.128 目的:把源服务器上/home/www.osyun ...
- React(0.13) 定义一个动态的组件(属性)
<!DOCTYPE html> <html> <head> <title>React JS</title> <script src=& ...
- JQuery UI - draggable(转)
·概述 在任何DOM元素启用拖动功能.通过单击鼠标并拖动对象在窗口内的任何地方移动. 官方示例地址:http://jqueryui.com/demos/draggable/ 所有的事件回调函数都有两个 ...
- 如何禁用Visual Studio 2013的浏览器链接功能
VS2013新增的Browser Link功能虽然“强大”,但我并不需要. 但默认是开启的,会在页面中自动添加如下的代码,真是烦人! <!-- Visual Studio Browser Lin ...
- Oracle命令(二):Oracle数据库几种启动和关闭方式
一.Oracle数据库几种启动方式 1.startup nomount 非安装启动,这种方式下启动可执行:重建控制文件.重建数据库,读取init.ora文件,启动instance,即启动SGA和后台进 ...
- Java设计模式(八)----代理模式
代理模式 1.生活中: 代理就是一个人或者一个组织代表其它人去做一件事的现实生活中的. 在一些情况下,一个客户不想或者不能够直接引用一个对象,而代理对象能够在client和目标对象之间起到中介的作用. ...