boost.asio的async_write_some存在的坑

博客讨论了在使用Boost.ASIO库的async_write_some时遇到的问题,包括跨线程调用限制和对方未读取导致发送缓冲区满的情况。当服务器不读取客户端发送的数据时,可能导致客户端内存耗尽,因为async_write_some的回调不会被触发,预分配的缓冲区无法释放。解决办法包括加锁同步、设置定时器检查状态或者调整发送策略以防止内存泄漏。

boost.asio的async_write_some看起来很方便,但使用起来很复杂,主要有两个方面:

  1. async_write_some经常与io_context不在同一线程,async_write_some同一时刻只能由一个线程调用,需要加锁,同时需要与io_context所在线程的其他异步方法同步,如关闭sock的时机。
  2. 当对方一直不读取缓冲区,就会造成本方的socket发送缓冲区爆满,此种情况需要怎样处理?

第一种情况就需要根据业务情况加各种锁了。现在只讨论当对方一直不读缓冲区的情况。测试如下
server和client建立连接后,client向server发送1000000个1024字节流,但server不读取内容。
结果:
不再回调,内存增长速度很快

发送端client在async_write_some的第2687次回调函数后就不再有回调了,但async_write_some一直在调用直到发送1000000次,内存一直在增长,所以当我们使用async_write_some时遇到这种情况,很容易造成内存耗尽,因为预先分配的buf会在回调函数中free掉,但此时回调函数永远不会被回调。

不能直接发现此类错误的话,就需要加个定时器检测状态了,用起来挺麻烦。
测试代码如下:

class LIBTEST_BOOST_DLL TcpServer
{
   
   
public:
	typedef  boost::asio::ip::tcp::socket tcp_socket_t;
	typedef  boost::asio::ip::tcp::acceptor tcp_acceptor_t;
	typedef  boost::asio::ip::tcp::endpoint tcp_endpoint_t;
	typedef  boost::asio::io_context io_context_t;
	TcpServer(io_context_t &io, const tcp_endpoint_t& endpoint);
	void Accept();
	void ReadHandler(tcp_socket_t *sock);
private:
	tcp_acceptor_t acceptor_;
	io_context_t *io_;
	uint64_t cnt_ = 0;
};
class LIBTEST_BOOST_DLL TcpClient
{
   
   
public:
	typedef  boost::asio::ip::tcp::socket tcp_socket_t;
	typedef  boost::asio::ip::tcp::endpoint tcp_endpoint_t;
	typedef  boost::asio::io_context io_context_t;
	TcpClient(io_context_t &io);
	void Connect(const tcp_endpoint_t& endpoint);
	void Write();
private:
	tcp_socket_t sock_;
	io_context_t  *io_;
	uint64_t cnt_ = 0;
};
TcpServer::TcpServer(io_context_t &io, const tcp_endpoint_t& endpoint)
	:acceptor_(io,endpoint
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值