Python 通过破裂的管道发送数据

Python 通过破裂的管道发送数据,python,sockets,Python,Sockets,当我将套接字连接到服务器套接字,并且服务器套接字在给定时间关闭时,我在客户端得到一个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

当我将套接字连接到服务器套接字,并且服务器套接字在给定时间关闭时,我在客户端得到一个
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
客户端输出为:

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
连接
有联系的
发送b'ping'
我发了一声“平”。传输的5字节
>> 
发送b'pang'
发出“砰”。传输的5字节
>> 
发送“退出”
发送“退出”。传输的5字节
>> 
发送b'ping'
我发了一声“平”。传输的5字节
>> 
发送b'pang'
回溯(最近一次呼叫最后一次):
文件“/client.py”,第10行,在
sent=s.send(msg+b'\r')
断管错误:[Errno 32]断管
为什么我在最后一次
pang
之后得到
BrokenPipeError
,而不是在
ping
之后

退出后发送
ping
时,为什么
发送
返回5

为什么在服务器关闭后管道没有立即断开



编辑:发送
exit
后,除非服务器控制台已打印
server down
,,否则我不会在客户端控制台上按enter键。发送功能仅确保数据已传输到套接字缓冲区。当服务器关闭时,它发送一个FIN,ACK数据包,客户端只回复ACK。在客户端调用close方法之前,客户端的套接字不会关闭。然后连接“半开”


当客户机再次向关闭的服务器套接字发送数据时,服务器将使用RST进行回复,客户机将中止连接。请参阅关于半开连接和其他异常的说明。但是,套接字在send方法返回后关闭。这就是为什么只有下一次发送才会在BrokenPipe上崩溃,因为连接现在也从客户端关闭。

这就是为什么我将
输入放入客户端的原因。在服务器控制台上打印最后一次接收之前,我不会按enter键。即便如此,我还是收到了那张破碎的一号发来的太晚了。
send
的返回值是什么意思?这么多字节已经交给了操作系统?给我的NIC?或者使用TCP,它们确实在另一端被接收?我测试了运行Wireshark的代码。当您调用close()时,FIN,ACK似乎是从服务器发送的。然而,客户端并没有像它应该的那样发回FIN、ACK,甚至调用shutdown(SHUTU RDWR)。所以我想对于客户端来说,连接仍然是开放的。发送新数据时,所有字节都放入缓冲区,操作成功。但是,当传输时,客户端接收到RST,然后才关闭其套接字。因此,以下发送失败。有有趣的信息。在更好地了解您的问题后编辑了答案。