通过损坏的管道发送数据

时间:2014-01-07 17:21:58

标签: 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 ( ('', 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

为什么sendping之后发送exit时会返回5?

为什么服务器关闭后管道没有立即损坏?


编辑:发送exit后,除非服务器控制台已打印Server down,否则我不会在客户端控制台上按Enter键。

1 个答案:

答案 0 :(得分:1)

send函数仅确保数据已传输到套接字缓冲区。当服务器关闭时,它会发送一个FIN,ACK数据包,客户端只回复ACK。在客户端也调用close方法之前,客户端的套接字不会关闭。然后连接“半开”。

当客户端再次将数据发送到已关闭的服务器套接字时,服务器将回复RST,客户端应将该连接中止。有关半开连接和其他异常的信息,请参阅http://tools.ietf.org/search/rfc793#page-33。但是,在send方法返回后,套接字将关闭。这就是为什么只有下一个发送将在BrokenPipe上崩溃,因为现在连接也从客户端关闭。

相关问题