A couple of options:
- You can set a timeout on the the socket used in the thread so that it returns from blocking after a period of time.
- Use
select.select()
with a timeout to poll a socket for data, periodically checking if the thread should exit.
Example of #1:
import threading
import socket
import select
# A server that echos only the first data received from a client
def server():
s = socket.socket()
s.bind(('',5000))
s.listen()
print('server: running')
while True:
c,a = s.accept()
print('server: client connected')
with c: # closes client socket when with block exits
echoed = False
while True:
data = c.recv(1024)
if not data: break
if not echoed:
print('server: responding',data)
c.sendall(data)
echoed = True
print('server: client disconnected')
def client():
s = socket.socket()
s.connect(('localhost',5000))
with s: # closes client socket when with block exits
try:
s.settimeout(5) # 5-second timeout if no data received.
print('client: send one')
s.sendall(b'one')
print('client: got',s.recv(1024))
print('client: send two')
s.sendall(b'two')
print('client: got',s.recv(1024)) # this will timeout
except socket.timeout:
print('client: timed out')
# Start server thread.
# As a daemon, it will exit if main thread and client thread both exit.
threading.Thread(target=server,daemon=True).start()
t = threading.Thread(target=client)
t.start()
t.join() # wait for client thread to exit.
t = threading.Thread(target=client)
t.start()
t.join() # wait for client thread to exit.
Output:
server: running
client: send one
server: client connected
server: responding b'one'
client: got b'one'
client: send two
client: timed out
server: client disconnected
client: send one
server: client connected
server: responding b'one'
client: got b'one'
client: send two
client: timed out
Note server didn't print that the second client disconnected. Since it is a daemon thread, it was terminated when the main thread and client thread both exited, and didn't have time to recognize the client disconnected after timeout. If you want cleaner exit behavior, don't use daemon threads.