Python套接字服务器停留在接收数据上

时间:2018-12-13 05:20:14

标签: python sockets client-server

我的简单套接字服务器/客户端测试遇到了死锁问题。查看代码

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来避免从头开始编写套接字服务器的麻烦,但是我还没有得到这个模块。

1 个答案:

答案 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()