什么原因导致ENOTCONN错误?

时间:2009-05-22 21:17:59

标签: sockets

我目前正在维护一些Web服务器软件,我需要执行大量的I / O操作。 read()write()close()shutdown()调用在套接字上使用时,有时可能会引发ENOTCONN错误。这个错误究竟是什么意思?触发它的条件是什么?我似乎永远不会在本地重现它,但有些用户可以。

现在我只是在ENOTCONNclose()提出时忽略shutdown(),因为它似乎无害,但我不完全确定。

编辑:

  • 我绝对相信connect()来电成功了。我检查它的返回值。
  • ENOTCONN通常由close()shutdown()提出。我很少看到read()write()提升ENOTCONN

5 个答案:

答案 0 :(得分:18)

如果您确定TCP连接的任何一方都没有关闭连接,那么听起来像远程端正在关闭连接。

正如其他人所指出的那样,

ENOTCONN只是意味着套接字没有连接。这并不一定意味着connect失败了。套接字可能以前已经连接过,但是在调用时却没有导致ENOTCONN

这与以下不同:

  • ECONNRESET:连接的另一端发送了TCP重置数据包。如果另一端拒绝连接,或者不承认它已经连接,可能会发生这种情况。
  • ETIMEDOUT:这通常仅适用于connect。如果连接尝试在依赖于系统的时间内未成功,则会发生这种情况。
某些与套接字相关的系统调用有时会在与EPIPE大致相同的条件下返回

ENOTCONN。例如,在某些系统上,EPIPEENOTCONNsend返回时是同义词。

虽然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)

这是因为,在关闭()套接字的那一刻,你有套接字缓冲区中的数据等待传递给已关闭()或关闭()其接收套接字的远程方。 我还没有完全理解套接字是如何工作的,我更像是一个菜鸟,而且我甚至找不到实现这个“关闭”功能的文件,但是看到实际上没有用户手册对我开始的整个套接字的事情尝试所有可能性,直到我在“受控”环境中得到错误。它可能是别的东西,但经过多次尝试后,这些是我解决的解释:

  • 如果在远程端关闭连接后发送数据,则在关闭()时会出现错误。
  • 如果您在远程端关闭连接之前发送数据但在另一端没有收到(),则可以关闭()一次,下次尝试关闭()时,您会收到错误。
  • 如果您没有发送任何数据,只要远程端没有关闭(),您就可以关闭所需的所有时间。一旦远程端有shutdown(),如果你尝试shutdown()并且套接字已经关闭(),你就会收到错误。

答案 3 :(得分:0)

传输端点未连接

套接字与面向连接的协议相关联,尚未连接。这通常是编程缺陷。

来自:http://www.wlug.org.nz/ENOTCONN

答案 4 :(得分:0)

如果您确定首先正确连接,ENOTCONN最有可能是由fd关闭(可能是在另一个帖子中)?你正处于请求的中间,或者当你处于请求的中间时,连接就会丢失。

在任何情况下,都表示套接字未连接。继续清理那个插座。它死了。在调用close()shutdown()时没问题。