我的简单套接字服务器/客户端测试遇到了死锁问题。查看代码
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()
据我所见,我的服务器可能不知道它已收到完整数据。因此,下一个self.request.recv()
调用会卡住。但是为什么不例外呢?还是为什么如果没有收到有效数据就不能简单地返回None
?
我尝试使用socketserver
来避免从头开始编写套接字服务器的麻烦,但是我还没有得到这个模块。
答案 0 :(得分:2)
以下是一些往返json
消息的更正:
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()