第一次发送到断开连接的套接字成功
Sending to a disconnected socket succeeds the first time
在 TCP 客户端-服务器通信中,当客户端在服务器断开连接后尝试向服务器发送消息时,第一次尝试 send()
(据称)成功,所有后续尝试都失败并显示 [Errno 32] Broken pipe
.最小示例:
import socket
import sys
import time
SERVER_ADDR = ("127.0.0.1", 65432)
def server(s):
s.bind(SERVER_ADDR)
s.listen()
print(f"Server listening for clients at {SERVER_ADDR}")
conn, addr = s.accept()
with conn:
print("Connected by", addr)
def client(s, msg):
s.connect(SERVER_ADDR)
time.sleep(1)
for i in range(1, 10):
print(f"Sending {msg} - attempt {i}")
try:
nbytes = s.send(msg)
print(f"{nbytes} bytes sent out of {len(msg)} in total")
except OSError as ex:
print(ex)
if __name__ == "__main__":
msg = " ".join(sys.argv[1:]).encode("utf8")
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
if msg:
client(s, msg)
else:
server(s)
- 启动服务器:
python run.py
Server listening for clients at ('127.0.0.1', 65432)
- 启动客户端:
python run.py hello world
Sending b'hello world' - attempt 1
11 bytes sent out of 11 in total
Sending b'hello world' - attempt 2
[Errno 32] Broken pipe
Sending b'hello world' - attempt 3
[Errno 32] Broken pipe
Sending b'hello world' - attempt 4
[Errno 32] Broken pipe
Sending b'hello world' - attempt 5
[Errno 32] Broken pipe
Sending b'hello world' - attempt 6
[Errno 32] Broken pipe
Sending b'hello world' - attempt 7
[Errno 32] Broken pipe
Sending b'hello world' - attempt 8
[Errno 32] Broken pipe
Sending b'hello world' - attempt 9
[Errno 32] Broken pipe
- 为什么会这样?
- 我怎样才能 (a) 使第一次尝试也失败,或者 (b) 在发送之前检测连接是否有效?
Why does this happen?
this answer to Writing to a closed, local TCP socket not failing里面有详细的解释。
How can I either (a) make the first attempt fail too, or (b) detect if the connection is alive before sending?
您可以通过强制服务器立即关闭套接字来使第一次尝试失败,使用 SO_LINGER
套接字选项,在 s.accept
行之后:
conn.setsockopt(socket.SOL_SOCKET, socket.SO_LINGER, struct.pack('ii', 1, 0))
在 TCP 客户端-服务器通信中,当客户端在服务器断开连接后尝试向服务器发送消息时,第一次尝试 send()
(据称)成功,所有后续尝试都失败并显示 [Errno 32] Broken pipe
.最小示例:
import socket
import sys
import time
SERVER_ADDR = ("127.0.0.1", 65432)
def server(s):
s.bind(SERVER_ADDR)
s.listen()
print(f"Server listening for clients at {SERVER_ADDR}")
conn, addr = s.accept()
with conn:
print("Connected by", addr)
def client(s, msg):
s.connect(SERVER_ADDR)
time.sleep(1)
for i in range(1, 10):
print(f"Sending {msg} - attempt {i}")
try:
nbytes = s.send(msg)
print(f"{nbytes} bytes sent out of {len(msg)} in total")
except OSError as ex:
print(ex)
if __name__ == "__main__":
msg = " ".join(sys.argv[1:]).encode("utf8")
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
if msg:
client(s, msg)
else:
server(s)
- 启动服务器:
python run.py
Server listening for clients at ('127.0.0.1', 65432)
- 启动客户端:
python run.py hello world
Sending b'hello world' - attempt 1
11 bytes sent out of 11 in total
Sending b'hello world' - attempt 2
[Errno 32] Broken pipe
Sending b'hello world' - attempt 3
[Errno 32] Broken pipe
Sending b'hello world' - attempt 4
[Errno 32] Broken pipe
Sending b'hello world' - attempt 5
[Errno 32] Broken pipe
Sending b'hello world' - attempt 6
[Errno 32] Broken pipe
Sending b'hello world' - attempt 7
[Errno 32] Broken pipe
Sending b'hello world' - attempt 8
[Errno 32] Broken pipe
Sending b'hello world' - attempt 9
[Errno 32] Broken pipe
- 为什么会这样?
- 我怎样才能 (a) 使第一次尝试也失败,或者 (b) 在发送之前检测连接是否有效?
Why does this happen?
this answer to Writing to a closed, local TCP socket not failing里面有详细的解释。
How can I either (a) make the first attempt fail too, or (b) detect if the connection is alive before sending?
您可以通过强制服务器立即关闭套接字来使第一次尝试失败,使用 SO_LINGER
套接字选项,在 s.accept
行之后:
conn.setsockopt(socket.SOL_SOCKET, socket.SO_LINGER, struct.pack('ii', 1, 0))