In a TCP client-server communication, when the client attempts to send to the server after the latter has disconnected, the first attempt to send()
(allegedly) succeeds and all subsequent attempts fail with [Errno 32] Broken pipe
. Minimal example:
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)
- Start the server:
python run.py
Server listening for clients at ('127.0.0.1', 65432)
- Start the client:
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
- Why does this happen?
- How can I either (a) make the first attempt fail too, or (b) detect if the connection is alive before sending?