有哪些情况下,close() 比 shutdown() 更优?

5

我是一个开源项目的开发人员,最近遇到了一些问题。服务器认为它已经完全响应了一个socket(即对于失败请求,它已经发送了回复或关闭了其自身),而客户端则陷入了轮询中。通过一些研究,我发现close()并不总是会生成POLLHUP事件,但shutdown(sock,2)可以。

鉴于此,我考虑在错误处理事件中添加shutdown(sock,2)(除了close()调用外)。有人知道这样做可能会导致什么问题吗?我是否想错了?我认为如果服务器认为socket已关闭,则客户端肯定不应尝试使用该socket进行任何其他操作,我想不出不添加此方法的理由,但我没有长时间使用TCP连接,希望能得到一些建议。


我推荐阅读以下内容:https://dev59.com/DXRC5IYBdhLWcg3wG9Nb - brain
大脑,这是一篇有趣的阅读,但它没有给我任何理由不想在关闭时调用关闭。 - dbeer
2个回答

3
你需要弄清楚为什么关闭套接字不会导致它被关闭。最有可能的原因是存在另一个描述符访问同一端点。只有当关闭最后一个端点时,才会导致隐式关闭。
你曾经复制过文件描述符吗?你是否确保在所有子进程中都关闭了它?如果套接字在父进程中,在fork此进程之前,父进程是否关闭了他们的副本?

David,感谢你的建议。我有一种感觉,问题在于追踪你所说的内容。我相信我已经删除了代码中所有的forks,改用了线程,但我会检查是否存在dups。不过有一个问题——当close()被正确关闭时,它是否总是会导致关闭? - dbeer
如果关闭了最后一个引用该端点的描述符,则关闭会导致隐式关闭。隐式关闭的行为取决于“关闭时延迟”的设置。 - David Schwartz
“close”不会返回错误信息。因此,它几乎从来不能替代“shutdown”。你不知道你发送的内容是否已被接收。 - usr

0

POLLHUP 不是测试关闭连接的正确方法。您应该测试文件描述符是否变为可读,并随后返回零长度读取。这是文件结束的定义。


R,该代码使用set:pollset.events = POLLIN | POLLHUP的poll()函数。由于我无法控制的原因,我不能改变它从poll()模型中退出。无论如何,客户端都会在该轮询上阻塞直至超时发生。 - dbeer
1
是的,然后检查 POLLIN。EOF 是一个零长度读取,显示为可供读取的输入。 - R.. GitHub STOP HELPING ICE
1
-1 POLLHUP 是在某些系统上(例如MacOS)检查的正确方式;POSIX规范允许两种方式。因此,如果您想要可移植性,确实需要检查 POLLHUP|POLLIN - Chris Dodd
代码确实检查了POLLIN和POLLHUP(抱歉我不小心发布了然后不得不编辑),但我的问题仍然存在。 - dbeer
我认为您需要详细说明客户端和服务器正在执行的操作。展示一些代码或者最后几个系统调用的strace,以便客户端挂起并没有意识到服务器已关闭连接,这可能就足够了。 - R.. GitHub STOP HELPING ICE
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接