Synopsis: server hangs on socket.recv() even though a socket.settimeout() was set.
Have a simple socket based server that loops over commands (simple text messages) sent from client(s) until it receives an 'end' command. I simulate a broken client by - making a connection - sending a command - receive the result - exit (never sending the 'end' command to server)
The whole system worked perfectly when the server/client protocol was adhered to, but with the broken client simulation the server is NOT timing out on the recv.
Relevant server code (simplified):
ip = '192.168.77.170'
port = 12345
args = { app specific data }
with socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0) as serverSock:
serverSock.bind((ip, port))
serverSock.listen()
while True:
sock, addr = serverSock.accept()
thread = threading.Thread(target=session, args=(sock, args))
thread.name = "client {}".format(addr)
thread.daemon = True
thread.start()
def session(sock, args):
sess = threading.local()
sess.sock = sock
sess.__dict__.update(args)
print("-" * 60)
print("Session opened from={addr}.".format(addr=sock.getpeername()))
sock.settimeout(10.0)
while True:
try:
print('about to wait on recv', sock.gettimeout())
cmd = recvString(sock)
print('got cmd =', cmd)
if cmd.startswith('foo'): doFoo(sess, cmd)
elif cmd.startswith('bar'): doBar(sess, cmd)
elif cmd.startswith('baz'): doBaz(sess, cmd)
elif cmd.startswith('end'): break
else:
raise Exception("Protocol Error: bad command '{}'".format(cmd))
except TimeoutError as err:
print("Error protocol timeout")
break
finally:
try:
sock.close()
except:
pass
print("Session closed.")
def recvString(sock):
buff = bytearray()
while True:
b = sock.recv(1)
if b == b'\x00': break
buff += b
return buff.decode() if len(buff) else ''
When running with broken client I get
> about to wait on recv cmd 10.0
> got cmd = foo
> about to wait on recv cmd 10.0
waits forever (and has very high CPU consumption to add insult to injury)
I've RTFM'd thoroughly and multiple times, and looked at other similar SO postings and all indicate that a simple settimeout() should work. Can't see what I'm doing wrong. Any help greatly appreciated.
1条答案
按热度按时间vwkv1x7d1#
如果对等体关闭连接,则
sock.recv(1)
将返回b''
,即没有数据。这种情况没有考虑在内。结果将出现一个无休止的忙碌循环,其中sock.recv(1)
将返回b''
,然后再次被调用,并立即返回b''
等。这也解释了高CPU。