Python socketserver застрял при получении данных - PullRequest
0 голосов
/ 13 декабря 2018

Я попал в тупиковую ситуацию с моим простым тестом socketserver / client.См. Код

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 голосов
/ 13 декабря 2018

Вот некоторые исправления для сообщения 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()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...