Reputation: 11580
I got into a deadlock issue with my simple socketserver/client test. See code
import pickle, json, socket, socketserver, threading
class ServerHandler(socketserver.BaseRequestHandler):
def __init__(self, request, client_address, server):
self.message = b''
socketserver.BaseRequestHandler.__init__(self, request, client_address, server)
def handle(self):
while True:
try:
# STUCK here when data is fully received.
data = self.request.recv(1024)
# STUCK end
if data is not None:
if len(data) > 0:
self.message += data
else:
break
else:
break
except:
break
self.request.send(self.message)
if __name__ == '__main__':
address = ('localhost', 10000)
server = socketserver.TCPServer(address, ParameterHandler)
ip, port = server.server_address
th = threading.Thread(target=server.serve_forever)
th.setDaemon(True)
th.start()
# Client
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.connect((ip, port))
s.settimeout(0.2)
message = pickle.dumps(json.loads(open('test.json').read()))
lenSent = s.send(message)
server.shutdown()
s.close()
server.socket.close()
From what I can see, my server probably does not know it has received the full data. So the next self.request.recv()
call gets stuck. But why isn't it an exception? or why can‘t it simply return None
if no valid data is received?
I try to use socketserver
to save the trouble of writing a socket server from scratch, but I don't get this module yet.
Upvotes: 1
Views: 1884
Reputation: 177406
Here's some corrections to round-trip a json
message:
import json, socket, socketserver, threading
class ServerHandler(socketserver.BaseRequestHandler):
# handle should return when the server is done with the connection
def handle(self):
message = b''
while True:
data = self.request.recv(1024)
if not data: # b'' when client shuts down writing on socket.
break
message += data
self.request.sendall(message) # sendall to ensure sending the full message back.
if __name__ == '__main__':
address = ('localhost', 10000)
server = socketserver.TCPServer(address, ServerHandler)
ip, port = server.server_address
th = threading.Thread(target=server.serve_forever)
th.setDaemon(True)
th.start()
# Client
s = socket.socket()
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.connect((ip, port))
# pickle can be exploited to execute code
message = json.dumps([1,2,3,4]) # returns `str` on Python 3
lenSent = s.sendall(message.encode()) # encode to `bytes`
s.shutdown(socket.SHUT_WR) # client has completed sending.
recvd = b''
while True:
data = s.recv(1024)
if not data: break # b'' when server closes connection.
recvd += data
print(json.loads(recvd))
s.close()
server.shutdown()
server.socket.close()
Upvotes: 3