假设您使用的是标准套接字模块,您应该捕获socket.error: (32, 'Broken pipe') 异常(不是其他人建议的 IOError)。这将在您描述的情况下引发,即发送/写入远程端已断开连接的套接字。
import socket, errno, time
# setup socket to listen for incoming connections
s = socket.socket()
s.bind(('localhost', 1234))
s.listen(1)
remote, address = s.accept()
print "Got connection from: ", address
while 1:
try:
remote.send("message to peer\n")
time.sleep(1)
except socket.error, e:
if isinstance(e.args, tuple):
print "errno is %d" % e[0]
if e[0] == errno.EPIPE:
# remote peer disconnected
print "Detected remote disconnect"
else:
# determine and handle different error
pass
else:
print "socket error ", e
remote.close()
break
except IOError, e:
# Hmmm, Can IOError actually be raised by the socket module?
print "Got IOError: ", e
break
请注意,第一次写入已关闭的套接字时并不总是会引发此异常 - 更常见的是第二次写入(除非第一次写入时写入的字节数大于套接字的缓冲区大小)。您需要记住这一点,以防您的应用程序认为远程端在可能已经断开连接时收到了第一次写入的数据。
您可以使用select.select()(或poll)减少这种情况的发生(但不能完全消除)。在尝试写入之前检查准备好从对等方读取的数据。如果select 报告有可从对等套接字读取的数据,则使用socket.recv() 读取它。如果这返回一个空字符串,则远程对等方已关闭连接。因为这里仍然存在竞争条件,所以您仍然需要捕获并处理异常。
Twisted 非常适合这类事情,但是,听起来您已经编写了相当多的代码。