我目前正在维护一些Web服务器软件,我需要执行大量的I / O操作。 read()
,write()
,close()
和shutdown()
调用在套接字上使用时,有时可能会引发ENOTCONN
错误。这个错误究竟是什么意思?触发它的条件是什么?我似乎永远不会在本地重现它,但有些用户可以。
现在我只是在ENOTCONN
和close()
提出时忽略shutdown()
,因为它似乎无害,但我不完全确定。
编辑:
connect()
来电成功了。我检查它的返回值。ENOTCONN
通常由close()
和shutdown()
提出。我很少看到read()
和write()
提升ENOTCONN
。答案 0 :(得分:18)
如果您确定TCP连接的任何一方都没有关闭连接,那么听起来像远程端正在关闭连接。
正如其他人所指出的那样, ENOTCONN
只是意味着套接字没有连接。这并不一定意味着connect
失败了。套接字可能以前已经连接过,但是在调用时却没有导致ENOTCONN
。
这与以下不同:
ECONNRESET
:连接的另一端发送了TCP重置数据包。如果另一端拒绝连接,或者不承认它已经连接,可能会发生这种情况。ETIMEDOUT
:这通常仅适用于connect
。如果连接尝试在依赖于系统的时间内未成功,则会发生这种情况。EPIPE
大致相同的条件下返回 ENOTCONN
。例如,在某些系统上,EPIPE
和ENOTCONN
在send
返回时是同义词。
虽然shutdown
返回ENOTCONN
并不罕见,但由于此函数应该拆除TCP连接,我会惊讶地看到close
返回ENOTCONN
。它真的不应该那样做。
最后,正如dwc所提到的,EBADF
不应该适用于您的场景,除非您尝试对已经close
d的文件描述符进行某些操作。套接字断开连接(即TCP连接已断开)与关闭与该套接字关联的文件描述符不同。
答案 1 :(得分:1)
我相信ENOTCONN会被返回,因为shutdown()不应该返回ECONNRESET或其他更准确的错误。
假设另一方“只是”关闭连接是错误的。在TCP级别,另一方只能半连接(或中止)。如果双方都执行shutdown()(或close()),则连接是普通的完全关闭。如果双方都这样做,shutdown()实际上都成功了!
问题是shutdown()在普通(半)关闭连接时不成功,既不是第一个关闭连接,也不是第二个连接。 - 根据POSIX docs for shutdown()中列出的错误,ENOTCONN是最不合适的,因为其他指示传递给shutdown()的参数有问题(或处理请求的本地资源问题)。
那发生了什么?目前,所涉及的双方之间某处的NAT设备可能已经放弃了关联并发送了RESET数据包作为反应。重置连接在IPv4中非常常见,您可以在代码中的任何位置获取它们,甚至在shutdown()中屏蔽为ENOTCONN。
编码错误也可能是原因。例如,在非阻塞套接字上,connect()可以返回0而不指示成功连接。
答案 2 :(得分:1)
这是因为,在关闭()套接字的那一刻,你有套接字缓冲区中的数据等待传递给已关闭()或关闭()其接收套接字的远程方。 我还没有完全理解套接字是如何工作的,我更像是一个菜鸟,而且我甚至找不到实现这个“关闭”功能的文件,但是看到实际上没有用户手册对我开始的整个套接字的事情尝试所有可能性,直到我在“受控”环境中得到错误。它可能是别的东西,但经过多次尝试后,这些是我解决的解释:
答案 3 :(得分:0)
答案 4 :(得分:0)
如果您确定首先正确连接,ENOTCONN
最有可能是由fd
关闭(可能是在另一个帖子中)?你正处于请求的中间,或者当你处于请求的中间时,连接就会丢失。
在任何情况下,都表示套接字未连接。继续清理那个插座。它死了。在调用close()
或shutdown()
时没问题。