当我将套接字连接到服务器套接字,并且在给定时间服务器套接字关闭时,我在客户端获得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 ('>> ')
我启动服务器,然后启动客户端并按Enter键逐步浏览消息。
服务器输出为:
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
之后发送exit
时会返回5?
为什么服务器关闭后管道没有立即损坏?
编辑:发送exit
后,除非服务器控制台已打印Server down
,否则我不会在客户端控制台上按Enter键。
答案 0 :(得分:1)
send函数仅确保数据已传输到套接字缓冲区。当服务器关闭时,它会发送一个FIN,ACK数据包,客户端只回复ACK。在客户端也调用close方法之前,客户端的套接字不会关闭。然后连接“半开”。
当客户端再次将数据发送到已关闭的服务器套接字时,服务器将回复RST,客户端应将该连接中止。有关半开连接和其他异常的信息,请参阅http://tools.ietf.org/search/rfc793#page-33。但是,在send方法返回后,套接字将关闭。这就是为什么只有下一个发送将在BrokenPipe上崩溃,因为现在连接也从客户端关闭。