首页 > 解决方案 > boost tcp 套接字卡在 write_some

问题描述

我有一个 boost tcp ip 套接字卡在 write_some 函数中接收器部分卡在死锁中(这是另一个与 tcp 套接字无关的问题)。我成功地模拟了在接收线程中永远休眠的问题。

即使我重新启动发件人,它也会挂在同一行

有没有办法设置超时以防卡在这种状态以重新启动连接?如果我使用 async_write_some 这将是一个解决方案吗?

当我在发送方执行 gstack 时,我可以看到它卡在从 /lib64/libc.so.6 调用 poll() 的 write_some 函数中。在下一行

socket->write_some(boost::asio::buffer(pData ,nLength, error);

接收器网络状态 在此处输入图像描述

发件人 netstat,我看到一些 netstat 输出为 fin_wait1 的情况,在某些情况下它已建立(但代码仍然卡在 write_some 中)

在此处输入图像描述

初始化发送方套接字

socket = boost::make_shared<boost::asio::ip::tcp::socket>(boost::asio::ip::tcp::socket(io_service,boost::asio::ip::tcp::endpoint, 
boost::asio::ip::tcp::v4(),portNumber)))
    // Set a deadline for the asynchronous operation.
boost::asio::deadline_timer pConnectTimer = ...;
pConnectTimer->expires_from_now(boost::posix_time::seconds(10));
boost::asio::socket_base::keep_alive option(true);
socket->set_option(option);
// Start the asynchronous connect itself.
socket->async_connect(endpoint,boost::bind(&CrXdrQueuetoSocket::ConnectCallback, this, std::ref(pi_xdrTarget),
        socket,boost::asio::placeholders::error));

//Poll io service only one time
io_service .poll_one(); 

标签: tcpboost-asio

解决方案


使用我的水晶球:您是否在传递fds(例如供第三方或遗留代码使用)?

你可能会遇到一个经典的陷阱。

在套接字代码中,需要有一 (1) 个套接字所有者来关闭它。在并发代码中,确保在该时间点之后没有其他人拥有 fd 的副本非常重要,因为这会为竞争条件打开它。

例如,同一个 fd 在关闭后将被重新使用,然后另一个线程可能会使用 fd,认为它仍然是旧连接。

这个错误似乎不太可能,但人们很容易犯,因为他们觉得“它很安全,fd 已关闭,所以以后所有的操作都会失败”。

我已经在代码中发现了一些错误,在这些错误中,应用程序偶尔会意外地对数据库服务器进行模糊测试,因为它们会将任意数据发送到重新打开到 mysql 的连接。

请注意,close()您可以shutdown()取消所有挂起的操作并导致新操作失败,而不释放 fd 以供重用。


推荐阅读