首先,值得一提的是,在大多数情况下,最好在主处理程序循环中处理此问题,您可以在其中简单地测试 EOF(socket.recv() 收到的空字符串。但是,我遇到了测试的需要this 和 following 似乎比将另一个回调传递给线程以获取此状态等更好)
以下是我正在使用的,但我对此很陌生,所以如果有更好或更有效的方法,请提供反馈,我会更新这个答案。
似乎最好的方法是检查getpeername()(在这里测试socket.recv()很糟糕,因为我们的测试会改变缓冲区,例如。)
返回远程端点的地址。对于 IP 套接字,地址信息是一对 (hostaddr, port)。
如果失败,则会引发 socket.error [Errno 9] Bad file descriptor.
def is_socket_valid(socket_instance):
""" Return True if this socket is connected. """
if not socket_instance:
return False
try:
socket_instance.getsockname()
except socket.error as err:
err_type = err.args[0]
if err_type == errno.EBADF: # 9: Bad file descriptor
return False
try:
socket_instance.getpeername()
except socket.error as err:
err_type = err.args[0]
if err_type in [errno.EBADF, errno.ENOTCONN]: # 9: Bad file descriptor.
return False # 107: Transport endpoint is not connected
return True
注意:我在那里进行了第一个 if-check,因为我正在测试一个也可能为 None 的属性。
- 这并不像我想要的那样明确,但在我的测试中它似乎是准确的。
- 原始问题提到想知道未连接的原因。这并没有解决这个问题。
此外,另一个答案提到如果套接字的本地端关闭,fileno() 返回一个负数。我得到相同的错误 9。无论哪种方式,这都不会测试另一方是否有效。
>>> s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
>>> s.fileno()
10
>>> s.close()
>>> s.fileno()
---------------------------------------------------------------------------
error Traceback (most recent call last)
----> 1 s.fileno()
/tools/package/python/2.7.13/lib/python2.7/socket.pyc in meth(name, self, *args)
226
227 def meth(name,self,*args):
--> 228 return getattr(self._sock,name)(*args)
229
230 for _m in _socketmethods:
/tools/package/python/2.7.13/lib/python2.7/socket.pyc in _dummy(*args)
172 __slots__ = []
173 def _dummy(*args):
--> 174 raise error(EBADF, 'Bad file descriptor')
175 # All _delegate_methods must also be initialized here.
176 send = recv = recv_into = sendto = recvfrom = recvfrom_into = _dummy
error: [Errno 9] Bad file descriptor