#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. Спасибо за разъяснение