【发布时间】:2017-10-07 21:16:46
【问题描述】:
我有一个带有多个客户端/会话的 TCP 服务器。每个会话都有自己的线程用于从客户端接收数据,但只有一个线程(“writeThread”)来响应所有客户端。
现在有一个问题,如果客户端在“writeThread”正在写入此套接字期间关闭连接,则写入操作需要几秒钟才能注意到连接已远程关闭。有时它根本不会注意到,就在我手动为已安装的 sighandler 发送 signal 时,应用程序会检测到它并中断写操作。
时间在Logger::trace("start write"); 和Logger::trace("remote term, closed socket "); 之间测量
尽管这可能不是最好的设计,但是否有可能立即检测到关闭的连接,还是我真的必须重新设计?
bool myWrite(UINT8 *pu8_buffer, UINT32 u32_size)
{
bool b_success = false;
try
{
Logger::trace("start write");
b_success = (u32_size == boost::asio::write(_x_socket, boost::asio::buffer(pu8_buffer, u32_size)))
}
catch (boost::system::system_error &er)
{
if (er.code() == boost::asio::error::eof ||
er.code() == boost::asio::error::connection_reset)
{
boost::system::error_code x_er;
_x_socket.close(x_er);
if (!x_er)
{
Logger::trace("remote term, closed socket ");
}
else
{
Logger::err("remote term, closed socket failed");
}
}
}
catch(std::exception &ex)
{
Logger::err("write exception\n\t",ex.what());
}
catch(...)
{
Logger::err("write unknown exception",(uint32_t)this);
}
return b_success;
}
【问题讨论】:
-
TCP/IP 中有一个选项可以减少超时时间(一端注意到另一端不再存在所需的时间)。然而,由于 TCP/IP 是一种可靠且健壮的连接协议(并使用此时间重试尚未确认的数据包),因此减少超时可能会引入其他问题(例如虚假断开连接)。如果“另一端”正确关闭套接字,您将立即收到通知,但如果另一端停止响应(或存在其他连接问题),则会发生此超时。
-
@RichardCritten 你确定这是因为“太大”的 tcp 窗口大小吗?
-
不,不是没有数据包跟踪 - 它只是一个低挂选项。获取 wireshark 或类似的工具,查看网络上的数据包,看看是否有干净的关闭或只是超时。
-
@RichardCritten 你是对的,只要线路上有一个 RST-ACK,写入功能就会立即中止。所以我的问题/情况的一部分在另一边——谢谢。你能告诉我更多关于“低挂”选项的信息吗?可以从应用程序设置此超时还是 TCP 内部?也许你有一些有用的链接。
-
你没有指定平台,所以这里是微软的答案(在其他平台上类似)你可能想要
SO_SNDTIMEO选项:msdn.microsoft.com/en-us/library/windows/desktop/…
标签: c++ multithreading sockets tcp boost-asio