boost.asio的async_write_some看起来很方便,但使用起来很复杂,主要有两个方面:
- async_write_some经常与io_context不在同一线程,async_write_some同一时刻只能由一个线程调用,需要加锁,同时需要与io_context所在线程的其他异步方法同步,如关闭sock的时机。
- 当对方一直不读取缓冲区,就会造成本方的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

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

8144

被折叠的 条评论
为什么被折叠?



