c++ 服务器在客户端终止连接进程后不关闭 TCP 套接字连接

Posted

技术标签:

【中文标题】c++ 服务器在客户端终止连接进程后不关闭 TCP 套接字连接【英文标题】:c++ server doesn't close TCP socket connection after the connection process is killed on client 【发布时间】:2013-09-10 14:42:51 【问题描述】:

我遇到了一个对我来说很奇怪的问题

我在centos和客户端(也在centos上运行)部署了一个c ++应用程序(服务器),有一个程序将通过定时器连接服务器,这样当连接数达到1k时,定时器停止.

我可以运行以下命令来检测服务器上的连接:

netstat -nat |grep -i "端口"| grep "已建立"

目前还不错。但是,在我从客户端终止进程后,服务器上的 ESTABLISHED STATUS 中仍然存在大量连接。而且即使我关闭了客户端机器,第二天早上10多个小时后,我仍然能够在服务器上看到很多处于ESTABLISHED状态的活动连接。

即使在我终止进程时可能会丢失数据包,因此它无法通知服务器 TCP 连接已关闭,但我相信 TCP 中有一个默认的心跳(keepalive)机制可以检查连接是否正常活着。

通过上面提到的命令获取连接数是否可靠,否则服务器不释放关闭的连接会出现什么问题?

【问题讨论】:

netstat 应该没问题,是的,TCP 应该在 10 小时之前超时并关闭。 netstat 是否显示它已连接到以前的客户端地址?服务器对连接做了什么……它是停在 select 还是 recv 上? @mark 为什么?如果服务器没有尝试发送并且它没有读取超时,那么有什么超时? @EJP 你是对的......我从不使用堆栈的keepalive机制,而是选择通过应用程序层keepalives和select/recv超时对连接时间进行应用程序级控制......我什至从来没有意识到默认情况下未启用堆栈。 @mark 一旦持久连接被接受并建立,服务器只会将数据包从不同的服务器(不同的不相关连接)中继到客户端。客户端不断发送请求以获取数据包。服务器的作用与普通的 C/S 框架没有什么特别的不同。然而,这些是即时建立的并发连接(超过 50k)。我尝试了更少量的并发请求,但仍然有连接无法关闭,只是数量较少。这可能是它的原因吗? 我假设您增加了文件描述符限制以处理那么多同时连接?比如说 500 个同时连接,这一切都可以正常工作吗? 【参考方案1】:

TCP keepalive 的默认值约为 2 小时(在 BSD/Linux 实现中)。当您看到连接在 10 小时后仍然启动时,您确定您设置了 TCP keeaplives 选项吗?我认为您的应用程序可能没有明确设置 keepalive 选项。一种方法是使用 get socket 选项并传递 SO_TCPKEEPALIVE 来检查是否确实设置了 keepalive。如果没有设置,请继续设置。

您可能会发现此讨论很有帮助:How to use SO_KEEPALIVE option properly to detect that the client at the other end is down?

【讨论】:

【参考方案2】:

Keepalive 默认情况下是关闭的。 你必须在服务器端启用它,每个套接字。

【讨论】:

请确保 keepalive 选项默认关闭,并且连接应在 2 小时内关闭。我启用了该选项,真正听起来很奇怪的是,即使在客户端关闭一整夜之后,仍有一些连接处于 ESTABLISHED 状态 这没有意义。如果 keepalive 默认关闭,则连接不会“在两小时内关闭”。您必须在相关套接字上启用 keepalive 才能获得该行为。

以上是关于c++ 服务器在客户端终止连接进程后不关闭 TCP 套接字连接的主要内容,如果未能解决你的问题,请参考以下文章

面向连接的Socket服务端关闭问题

TCP连接的建立与终止

TCP四次挥手

C++ - 每个 Tcp 连接的进程

nginx - 超时后不正常的工作人员终止

TCP的保活机制