HTTP-сокет Python: не всегда получает все от клиента с отправленным JSON

#python #json #python-3.x #sockets #http

#python #json #python-3.x #сокеты #http

Вопрос:

Я кодировал серверный сокет на python, который способен получать HTTP-запрос от клиента с прикрепленной к нему полезной нагрузкой JSON и отображать его на стороне сервера. Проблема в том, что иногда (не регулярно) Я не получаю JSON, только заголовок HTTP (см. Код и пример вывода ниже)

С моим коллегой мы потратили целый день на безуспешное решение этой проблемы, поэтому мы были бы благодарны, если у кого-то есть советы или он уже сталкивался с такой проблемой и решил ее.

Вот сервер

 import socket, queue, select

HOST=''
PORT=20400


class Socket_Serv:  
    def creaSocket(self, SocketHTTP=None):
        if SocketHTTP is None:
            self.SocketHTTP = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            self.SocketHTTP.setblocking(0)
        else:
            self.SocketHTTP = SocketHTTP
    def listening(self,HOST,PORT):
        self.SocketHTTP.bind((HOST, PORT))
        self.SocketHTTP.listen(10)
        print("Listening on port : {}".format(PORT))
    

    def recept(self):
        inputs=[self.SocketHTTP]
        outputs=[]
        message_queue = {}
        while inputs:
            print ('n Waiting for message')
            rfile, wfile, exceptional = select.select(inputs, outputs, inputs)
            for sock in rfile:
                if sock is self.SocketHTTP:
                    connection, client_addr = sock.accept()
                    print ('Connection from'), client_addr
                    connection.setblocking(0)
                    inputs.append(connection)

                    message_queue[connection] = queue.Queue()
                else:
                    msg_recu = sock.recv(400)
                    if msg_recu:
                        msg_test = msg_recu.decode()
                        print(len(msg_test))
                        if len(msg_test) <= 400:
                            print ('received "%s" from %s' % (msg_recu, sock.getpeername()))
                            message_queue[sock].put(msg_recu)
                            if sock not in outputs:
                                outputs.append(sock)
                        else : 
                            print ('closing', client_addr, 'after wrong length')
                            if sock in outputs:
                                outputs.remove(sock)
                            inputs.remove(sock)
                            sock.shutdown(socket.SHUT_RD)
                            sock.close()
                    else :
                        print ('closing', client_addr, 'after reading no data')
                        if sock in outputs:
                            outputs.remove(sock)
                        inputs.remove(sock)
                        sock.shutdown(socket.SHUT_RD)
                        del message_queue[sock]
            for sock in wfile:
                try:
                    next_msg= message_queue[sock].get_nowait()
                except queue.Empty:
                    print ('output queue for', sock.getpeername(), 'is empty')
                    outputs.remove(sock)
                else:
                    print ('Envoi OK to %s', sock.getpeername())
                    sock.send(b"OK_OK")
                    print("Ecriture finie")
                    sock.shutdown(socket.SHUT_WR)
                    outputs.remove(sock)
                    sock.close()
                    Socket.recept()

if __name__ == '__main__':
    Socket= Socket_Serv()
    Socket.creaSocket()
    Socket.listening(HOST,PORT)
    Socket.recept()

  

Вот часть клиента, которая отправляет запрос

 
POST_DATA = (json.dumps({ "IP":internal_info.Get_ip() ,"version":VERSION , "UTC_TIME":str(internal_info.Get_time()) , "UUID":str(myuuid) })).encode("ascii")
        print(POST_DATA)
         try :
            with urllib.request.urlopen(ip,POST_DATA) as f :
                print(f.read().decode('utf-8'))
        except (urllib.error.URLError,http.client.HTTPException,ConnectionError) :
            print("HTTPError")
        finally:
            print("no")
  

И вот пример вывода

 Connection from

 Waiting for message
322
received "b'POST / HTTP/1.1rnAccept-Encoding: identityrnContent-Type: application/x-www-form-urlencodedrnContent-Length: 130rnHost: X.X.X.X:20400rnUser-Agent: Python-urllib/3.7rnConnection: closernrn{"IP": "X.X.X.X", "version": "1.1", "UTC_TIME": "2020-09-23 12:39:46.396360", "UUID": "dcc549c2-fd99-11ea-8c16-000c29102f8a"}'" from ('X.X.X.X', 60416)

 Waiting for message
Envoi OK to %s ('X.X.X.X', 60416)
Ecriture finie

 Waiting for message
Connection from

 Waiting for message
192
received "b'POST / HTTP/1.1rnAccept-Encoding: identityrnContent-Type: application/x-www-form-urlencodedrnContent-Length: 130rnHost: X.X.X.X:20400rnUser-Agent: Python-urllib/3.7rnConnection: closernrn'" from ('X.X.X.X', 60418)

 Waiting for message
Envoi OK to %s ('X.X.X.X', 60418)
Ecriture finie

 Waiting for message
Connection from

 Waiting for message
192
received "b'POST / HTTP/1.1rnAccept-Encoding: identityrnContent-Type: application/x-www-form-urlencodedrnContent-Length: 130rnHost: X.X.X..56:20400rnUser-Agent: Python-urllib/3.7rnConnection: closernrn'" from ('X.X.X..23', 60420)

 Waiting for message
Envoi OK to %s ('X.X.X..23', 60420)
Ecriture finie

 Waiting for message
Connection from

 Waiting for message
322
received "b'POST / HTTP/1.1rnAccept-Encoding: identityrnContent-Type: application/x-www-form-urlencodedrnContent-Length: 130rnHost: X.X.X..56:20400rnUser-Agent: Python-urllib/3.7rnConnection: closernrn{"IP": "X.X.X..23", "version": "1.1", "UTC_TIME": "2020-09-23 12:39:48.473513", "UUID": "ddfd343a-fd99-11ea-8c16-000c29102f8a"}'" from ('X.X.X..23', 60422)

 Waiting for message
Envoi OK to %s ('X.X.X..23', 60422)
Ecriture finie

 Waiting for message
Connection from

 Waiting for message
322
received "b'POST / HTTP/1.1rnAccept-Encoding: identityrnContent-Type: application/x-www-form-urlencodedrnContent-Length: 130rnHost: X.X.X..56:20400rnUser-Agent: Python-urllib/3.7rnConnection: closernrn{"IP": "X.X.X..23", "version": "1.1", "UTC_TIME": "2020-09-23 12:39:50.540748", "UUID": "df3dae38-fd99-11ea-8c16-000c29102f8a"}'" from ('X.X.X..23', 60424)

 Waiting for message
Envoi OK to %s ('X.X.X..23', 60424)
Ecriture finie

  

Как вы можете видеть, иногда я получаю все, иногда нет, и в поведении вывода нет логики. Сначала мы подумали о проблеме с буфером, но из-за нерегулярности это, вероятно, не решение. Мы пробовали много других способов отправки данных, таких как использование requests lib, но результат тот же.
Помимо того факта, что я довольно новичок в python, без ошибок на сервере во время выполнения довольно сложно устранить неполадки.

Комментарии:

1. Ваш сервер вообще не использует HTTP, т. Е. Нет надлежащей обработки HTTP-запроса и недопустимого HTTP-ответа. Кроме того, вы, кажется, предполагаете, что сингл recv всегда будет читать полное «сообщение». Это неверное предположение. TCP — это всего лишь поток байтов и не имеет встроенной семантики сообщений. Вам нужно правильно реализовать HTTP, т. Е. Прочитать HTTP, затем прочитать тело, пока не получите объявленную длину, а затем ответить правильным HTTP-ответом.

2. Понятно, тогда я буду искать другой способ реализации HTTP. Спасибо за разъяснение