C中的套接字:关闭套接字的正确方法

Posted

技术标签:

【中文标题】C中的套接字:关闭套接字的正确方法【英文标题】:Socket in C: Proper way to close socket 【发布时间】:2019-04-13 17:43:37 【问题描述】:

我经常看到使用套接字的服务器程序的示例代码。

(为简单起见,这里我不检查socket()或bind()等函数的返回值)

int sockfd = 0, newsockfd = 0;
struct sockaddr_in address;

sockfd = socket(AF_INET, SOCK_STREAM, 0);

bind(sockfd, (struct sockaddr*)&address, sizeof(address));
listen(sockfd, 1);

newsockfd = accept(sockfd, (struct sockaddr*)NULL, NULL);

... do some communication ...

close(newsockfd);

我在网上找到的大多数示例代码都有 close(newsockfd),但没有 close(sockfd)。 我的问题是不关闭 sockfd 是否真的正确

如果它是正确的,我想知道为什么。 我的理解是 sockfd 是文件描述符之一,并且 它似乎没有理由在不关闭程序的情况下退出程序。

更具体地说,我想知道当程序下次运行时,not-closure-sockfd 会导致绑定错误(例如,此套接字正在使用中......)。

如果你能帮助我,我真的很感激。 感谢您的宝贵时间。

【问题讨论】:

【参考方案1】:

sockfd 充当服务器套接字:它仅用于接受越来越多的传入连接。只要您必须接受和处理 newsockfd 上的新连接,您就可以保持 sockfd 的打开、绑定和侦听,从而保持当前连接,您正在从/向某个对等程序读取/写入。完成newsockfd 后,您将其关闭,如果需要,请在sockfd 上使用accept() 接受一个新的。以此类推。

【讨论】:

【参考方案2】:

当您停止收听时,您应该始终关闭 sockfd。

一些开发者不太关心不关闭 sockfd 的两个原因:

如果您的程序没有关闭就退出,操作系统会为您关闭 sockfd 大多数时候,服务器一直保持监听打开(例如:几个月)

但是,如果您的程序在某个事件上启动侦听套接字,然后在一段时间后将其关闭并循环,那么您必须关闭 sockfd,以防止在下一次迭代时出现错误 EADDRINUSE(地址已在使用中),并且内存泄漏。

另外,错误EADDRINUSE (Address already in use) 可能会出现在其他情况下,我在此不再详述。

【讨论】:

【参考方案3】:

如果程序退出,现代操作系统将自动释放应用程序分配的资源,如内存或打开的文件描述符(包括套接字)。因此,如果服务器套接字应该在整个程序中都可用(以便接受连接),则可以不显式关闭它,而是让操作系统在应用程序退出时执行此操作。

【讨论】:

以上是关于C中的套接字:关闭套接字的正确方法的主要内容,如果未能解决你的问题,请参考以下文章

Linux 中的优雅关闭服务器套接字

发送后如何正确关闭套接字(使用 IOCP)?

C++ Windows 套接字 - 在程序退出时关闭套接字

C 套接字服务器:读取所有未知长度 XMLHttpRequest 的正确方法是啥?

如何将字节数据从套接字写入 C 中的无符号字符向量? [关闭]

如何优雅地关闭异步服务器套接字? C#