Python socket 编程:send 返回 Broken pipe 错误?

版权声明:本文为博主原创文章,转载请注明原文出处。 https://blog.csdn.net/woay2008/article/details/88085655

在 socket 编程中常遇到的错误有我之前在这篇文章中提到的 ECONNRESET 错误,还有一种错误比较少遇见就是今天我要讲的 EPIPE 错误。在调用 send 函数时发送数据时可能会出现这种错误,这时程序会抛出如下异常:

socket.error: [Errno 32] Broken pipe

为什么会出现这种错误?先看看官方 man 2 write 文档对这个错误的描述:

EPIPE
fd is connected to a pipe or socket whose reading end is closed. When this happens the writing process will also receive a SIGPIPE signal. (Thus, the write return value is seen only if the program catches, blocks or ignores this signal.)

以上是说,在对一个已经关闭读端的管道或 socket 写入数据时,程序会收到 SIGPIPE 信号。管道的例子在这篇文章中我们已经见过。

今天举个简单的 socket 的例子,来探究为什么会出现这种错误。

客户端代码如下:

import socket
import time

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('127.0.0.1', 2222))

s.send('hello')
time.sleep(1)
s.send('hello')
s.send('hello')

s.close()

服务端代码如下:

import socket

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind(('127.0.0.1', 2222))
s.listen(5)

c, addr = s.accept()

c.recv(1024)

c.close()

在执行客户端程序1秒钟后,就会出现 Broken pipe 错误:

[root@localhost python]# python client.py 
Traceback (most recent call last):
  File "client.py", line 10, in <module>
    s.send('hello')
socket.error: [Errno 32] Broken pipe

抓包结果如下:

03:51:51.137047 IP 127.0.0.1.50870 > 127.0.0.1.2222: Flags [S], seq 2737957170, win 32792, options [mss 16396,sackOK,TS val 39403123 ecr 0,nop,wscale 5], length 0
03:51:51.137055 IP 127.0.0.1.2222 > 127.0.0.1.50870: Flags [S.], seq 2751472309, ack 2737957171, win 32768, options [mss 16396,sackOK,TS val 39403123 ecr 39403123,nop,wscale 5], length 0
03:51:51.137061 IP 127.0.0.1.50870 > 127.0.0.1.2222: Flags [.], ack 1, win 1025, options [nop,nop,TS val 39403123 ecr 39403123], length 0
03:51:51.137083 IP 127.0.0.1.50870 > 127.0.0.1.2222: Flags [P.], seq 1:6, ack 1, win 1025, options [nop,nop,TS val 39403123 ecr 39403123], length 5
03:51:51.137089 IP 127.0.0.1.2222 > 127.0.0.1.50870: Flags [.], ack 6, win 1024, options [nop,nop,TS val 39403123 ecr 39403123], length 0
03:51:51.137158 IP 127.0.0.1.2222 > 127.0.0.1.50870: Flags [F.], seq 1, ack 6, win 1024, options [nop,nop,TS val 39403123 ecr 39403123], length 0
03:51:51.139348 IP 127.0.0.1.50870 > 127.0.0.1.2222: Flags [.], ack 2, win 1025, options [nop,nop,TS val 39403137 ecr 39403123], length 0
03:51:52.140421 IP 127.0.0.1.50870 > 127.0.0.1.2222: Flags [P.], seq 6:11, ack 2, win 1025, options [nop,nop,TS val 39404140 ecr 39403123], length 5
03:51:52.140444 IP 127.0.0.1.2222 > 127.0.0.1.50870: Flags [R], seq 2751472311, win 0, length 0

不难分析,出现这个错误的过程如下:

  1. 客户端在睡眠过程中,服务端已经正常关闭了连接。
  2. 客户端被唤醒后,第一次 send 发送数据导致 socket 接收到 RST 报文。
  3. 第二次 send 再发送数据导致程序接收到 SIGPIPE 信号,出现 Broken pipe 错误。

所以我们可以得出这样一个结论:如果对端正常关闭了连接且之后 socket 上又收到 RST 报文,那么再在 socket 上执行send时会出现 Broken pipe 错误!

猜你喜欢

转载自blog.csdn.net/woay2008/article/details/88085655