客户端断开连接后,我是不是必须关闭服务器端的套接字?

Posted

技术标签:

【中文标题】客户端断开连接后,我是不是必须关闭服务器端的套接字?【英文标题】:Do I have to close the socket on the server side after client disconnects?客户端断开连接后,我是否必须关闭服务器端的套接字? 【发布时间】:2017-09-08 04:45:41 【问题描述】:

所以让我简化我正在处理的代码:

int fd = socket(...);
int client = accept(fd, ...);
while (true) 
    int bytes_read = recv(client, ...);
    if (bytes_read == 0) 
        break;
    
;

此时我已经知道客户端已断开连接(recv 返回 0)。但是我还需要打电话吗

close(client);

?

【问题讨论】:

好吧,我认为您需要这样做,因为 [我认为] 由于您没有关闭文件描述符,因此会造成内存泄漏。 如果你不调用 close(),并继续创建新的套接字(例如通过 accept()),那么最终你的进程的套接字表将被剩余的套接字填满,然后你的进程就赢了'不能再创建了,所以accept()、socket()等都会因为errno=EMFILE而失败,然后你的程序就不能再正常工作了:( 【参考方案1】:

是的。

当您recv() 0 字节时,这是内核让您知道远程主机已关闭其发送 端连接的方式。他们可能仍然打开套接字并且可以接收您发送的更多数据(但不回复)。

当您在 TCP 套接字上调用 close() 时,您正在做两件事:

    关闭套接字的本地端,让远程主机知道您也已完成传输。如果不这样做,您可能会让客户端挂起,等待您发送更多数据。 关闭文件描述符。这将释放进程打开文件表中的条目。如果不这样做,您会浪费资源,并且可能会发现自己的内存或可用文件描述符不足。大多数操作系统都对进程一次可以打开的文件描述符(或句柄)的数量有硬性限制。

【讨论】:

Ad1:不需要通知客户端(远程主机)(它已经死了),但需要释放连接表中的条目(它可能会先停留一段时间-wait state for some time) 这会在你的 (2) 中自动处理:它是通过 close(fd) 处理的 @wildplasser 回复:1 我认为你错过了我的观点。客户端可能没有“死”——他可能只调用了shutdown(fd, SHUT_WR),并且可能仍在等待来自服务器的更多数据。在这种情况下,他确实需要被告知。 没错;它可能是半封闭的。但我完全同意你的看法:调用 close(fd) 是要走的路。 @Jonathon 收到 EOF,调用关闭是没有意义的,因为对方已经关闭了连接或至少关闭了连接的发送部分。调用 shutdown() 将关闭连接的另一半,就像 close() 无论如何都会做的那样。关于“需要被告知”,close() 也会发生这种情况,无需调用 shutdown()。 谢谢@Meixner,但是为什么那个评论是针对我的呢?我很清楚close() 意味着shutdown()。我没有建议需要致电shutdown【参考方案2】:

您需要关闭描述符以释放绑定到它的资源。

【讨论】:

【参考方案3】:

答案是肯定的。原因是 accept() 分配内存, close() 释放内存。

想象一个理论上的情况,您的代码处于循环中,并且每次调用 accept() 时,它都会分配 1GB 的 RAM(假设它是一个非常低效的套接字库 :-))。每当您调用 close() 时,它都会释放 1GB 的 RAM。如果你从不调用 close(),那么在你用完内存之前,循环会发生多少次 accept()?

当然,accept() 只分配一小块内存,但最终你会耗尽内存,除非你对它做点什么。

【讨论】:

内存本身并没有真正通过问题。打开文件描述符的限制会咬你。我认为您需要重新表述您的答案,因为不清楚这句话是假设性的:“每次调用 accept(),它都会分配 1GB 的 RAM。”

以上是关于客户端断开连接后,我是不是必须关闭服务器端的套接字?的主要内容,如果未能解决你的问题,请参考以下文章

如何检查客户端是不是通过 C++ 中的 Winsock 断开连接?

如何在WebSocket的服务器侧检测客户端的断开连接

如何在socket.io中的断开事件上获取断开连接的客户端的套接字ID

Winsock - 客户端断开连接,关闭套接字循环/最大连接数

Perl-我如何知道套接字客户端何时断开连接(当用户关闭窗口/浏览器时)

Python 3.5.1 - Asyncio - 检查套接字客户端是不是已断开连接