標準のソケットモジュールを使用していると仮定すると、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
この例外は、閉じたソケットへの最初の書き込みで常に発生するとは限らないことに注意してください。通常は 2 回目の書き込みで発生します (最初の書き込みで書き込まれたバイト数がソケットのバッファー サイズよりも大きい場合を除きます)。リモート エンドが既に切断されている可能性があるときに、最初の書き込みからデータを受信したとアプリケーションが判断した場合に備えて、この点に留意する必要があります。
select.select()
(または)を使用すると、この発生率を減らすことができます (ただし、完全になくすことはできませんpoll
)。書き込みを試みる前に、ピアから読み取る準備ができているデータを確認してください。select
ピア ソケットから読み取ることができるデータがあると報告された場合は、 を使用して読み取りますsocket.recv()
。これが空の文字列を返す場合、リモート ピアは接続を閉じています。ここにはまだ競合状態があるため、例外をキャッチして処理する必要があります。
Twisted はこの種の作業には最適ですが、すでにかなりの量のコードを作成しているように思えます。