Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 方法来处理错误的文件描述符错误_C_Sockets_Recv - Fatal编程技术网

C 方法来处理错误的文件描述符错误

C 方法来处理错误的文件描述符错误,c,sockets,recv,C,Sockets,Recv,场景: 客户端和服务器之间已建立连接。客户端连接已关闭,客户端已销毁。在服务器端,检测到一些已关闭的连接,但有些未关闭。因此,存在类似悬空指针的套接字描述符。在这些套接字描述符上选择返回错误的文件描述符错误,但无法找到无效的fd 问题: 在上述场景中,如果客户端连接不存在,我应该如何处理这些错误的文件描述符。我可以对这些描述符调用recv()。的签名是: errorfds集合不提供生成错误条件的描述符列表,例如EBADF 您可以调用recv()或任何其他使用坏文件描述符的文件描述符的函数;您可能

场景:
客户端和服务器之间已建立连接。客户端连接已关闭,客户端已销毁。在服务器端,检测到一些已关闭的连接,但有些未关闭。因此,存在类似悬空指针的套接字描述符。在这些套接字描述符上选择返回错误的文件描述符错误,但无法找到无效的fd

问题: 在上述场景中,如果客户端连接不存在,我应该如何处理这些
错误的文件描述符
。我可以对这些描述符调用
recv()

的签名是:

errorfds
集合不提供生成错误条件的描述符列表,例如
EBADF


您可以调用
recv()
或任何其他使用坏文件描述符的文件描述符的函数;您可能会从调用的函数中返回一个
EBADF
错误(除非它在检测
EBADF
之前检测到不同的错误条件)。

我相信您搞错了不同的情况

如果在客户端关闭连接,并且您在服务器端套接字上调用select(),则会触发FD_READ,recv()将返回零,然后您可以在服务器端关闭套接字

如果连接丢失且服务器未接收到FIN信号,则需要在客户端和服务器之间设置心跳信号,并在每个服务器端套接字上设置计时器,以检测TCP半开放的情况


只有在已关闭的套接字上调用API时,“错误的文件描述符”错误才会发生。

recv()在这种情况下,返回0,如同与客户端的连接已关闭,但select返回同一套接字描述符的错误文件描述符。您可能需要区分系统认为的“错误文件描述符”和您认为的错误文件描述符。系统认为已关闭(或从未打开)的文件描述符不好。读取描述符的远端没有发送方这一事实并不是一个错误;文件描述符可能会报告为“就绪”,当您从中读取时,您会得到EOF指示(即读取零字节)。文件描述符不错;它永远不会返回任何数据。当
recv()
调用返回零时,您就可以断定客户端已经离开了。如果我选择了fd get set并执行recv(),我将在客户端关闭连接,同时在服务器端关闭连接返回0,我断定客户端已关闭。但在某些情况下,select将返回错误的文件描述符错误。您知道在哪种情况下,select返回描述符上的EBADF吗?您的意思是在TCP半开放的情况下,select将返回EBADF?否。对于TCP半开放套接字,select()将不返回任何内容,不返回读取事件,也不写事件。通常心跳计时器用于检测TCP半开套接字,然后将其关闭。为什么对于已变为坏的套接字描述符,select返回坏文件描述符,recv返回0?我认为情况是这样的:1)recv()返回0表示对等方关闭套接字;2) 插座关闭;3) select()返回“错误的描述符”。我不相信recv()可以在一个已经关闭的套接字上返回0。如果我使用fcntl(F_GETFD..)查找哪个套接字fd坏了,fcntl返回1并选择returns EBADF。在哪种情况下可能?
int select(int nfds, fd_set *restrict readfds,
           fd_set *restrict writefds, fd_set *restrict errorfds,
           struct timeval *restrict timeout);