當我將套接字連接到服務器套接字並且在給定時間服務器套接字關閉時,我在客戶端獲得了BrokenPipeError
。但是,下次我嘗試發送一些內容時,並不是在那之後。通過破損的管道發送數據
這裏一個SSCCE:
服務器:
#! /usr/bin/python3
import socket
s = socket.socket (socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt (socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind (('', 10100))
s.listen (1)
print ('Waiting on client')
client, _ = s.accept()
print ('Accepted')
data = b''
done = False
while not done:
data += client.recv (4096)
msgs = data.split (b'\r')
for msg in msgs [:-1]:
print ('received {}'.format (msg))
done = msg == b'exit'
data = msgs [-1]
s.close()
print ('Server down')
客戶:
#! /usr/bin/python3
import socket
s = socket.socket (socket.AF_INET, socket.SOCK_STREAM)
print ('Connecting')
s.connect (('localhost', 10100))
print ('Connected')
for msg in [b'ping', b'pang', b'exit', b'ping', b'pang']:
print ('Sending {}'.format (msg))
sent = s.send (msg + b'\r')
print ('Sent {}. {} bytes transmitted'.format (msg, sent))
input ('>> ')
我啓動服務器,然後在客戶端和回車鍵來逐步的消息。
服務器輸出:
Waiting on client
Accepted
received b'ping'
received b'pang'
received b'exit'
Server down
客戶端輸出是:
Connecting
Connected
Sending b'ping'
Sent b'ping'. 5 bytes transmitted
>>
Sending b'pang'
Sent b'pang'. 5 bytes transmitted
>>
Sending b'exit'
Sent b'exit'. 5 bytes transmitted
>>
Sending b'ping'
Sent b'ping'. 5 bytes transmitted
>>
Sending b'pang'
Traceback (most recent call last):
File "./client.py", line 10, in <module>
sent = s.send (msg + b'\r')
BrokenPipeError: [Errno 32] Broken pipe
爲什麼我得到BrokenPipeError
最後pang
之後,而不是後ping
?
爲什麼send
在發送ping
後返回5時exit
?
爲什麼在服務器關閉後不會立即損壞管道?
編輯:派遣exit
後,我不打客戶端控制檯上輸入,除非在服務器控制檯已經印刷Server down
。
這就是爲什麼我把'輸入'放在客戶端。直到服務器控制檯上最後一個接收打印完成,我才按回車鍵。即使如此,我發現這種破碎型發送得太晚了。 'send'的返回值是什麼意思?那麼多的字節已經交給了操作系統?到我的網卡?或者與TCP相比,他們確實已經在另一邊收到了? – Hyperboreus
我測試了運行Wireshark的代碼。當你調用close()時,看起來FIN,ACK是從服務器發送的。但是,客戶端不會像應該那樣發送FIN,ACK,甚至調用shutdown(SHUT_RDWR)。所以我猜想客戶端連接仍然是開放的。發送新數據時,所有字節都放入緩衝區,操作成功。但是,傳輸時客戶端收到一個RST,然後才關閉其套接字。因此下面的發送失敗。 [如何](http://docs.python.org/3.3/howto/sockets.html#using-a-socket)有一些有趣的信息。 – Cilyan
在更好地審視您的問題後編輯答案。 – Cilyan