подключение к сокету Python не может получить полное сообщение - PullRequest
0 голосов
/ 07 декабря 2018

Я использую следующий код для получения данных и дампа в файл.Но когда символы отправляются более 1500, он не может получить полное сообщение, следовательно, json не является правильным в файле.Это происходит неуверенно, то есть иногда принимается полный обмен сообщениями, а иногда происходит сбой.

Но эта проблема не возникает, когда мы одновременно используем logstash в качестве получателя.

Сценарий получателя:

s.listen(5)
while True:
    c, addr = s.accept()
    print('Got connection from', addr)
    json_data = c.recv(16384).decode() # Increasing this doesn't help
    json_dump = json.dumps(json_data)  

    if os.path.exists(destination_file):
        append_write = 'a'  # append if already exists
    else:
        append_write = 'w'  # make a new file if not
    dump_file = open(destination_file, append_write)
    dump_file.write(json_dump + '\n')
    dump_file.close()

    c.send(b'SUCCESS')
    c.close()

Сценарий отправителя

def send_data(socket_conn, data_stream):
    try:
        json_data = JSONEncoder().encode(data_stream)
        json_data = json_data
        socket_conn.send(json_data.encode())
        socket_conn.send(b'\n')
        socket_conn.close()
        return True
    except socket.error as msg:
        logging.error(msg, exc_info=True)
        return False

1 Ответ

0 голосов
/ 07 декабря 2018
  json_data = c.recv(16384).decode() # Increasing this doesn't help

TCP - это потоковый протокол, а не протокол сообщений.Нет гарантии, что если отправитель отправит все данные с одним send, то они могут быть получены с одним recv.

Если одноранговый узел отправляет только один JSON, а затем закрывает соединение, получатель может просто recv, пока больше не будет доступных данных (recv возвращает пустое сообщение) и объединить части:

 data = b''
 while True:
     buf = c.recv(16384)
     if not buf:
         break
     data = data + buf
 json_data = data.decode()

Если вместо этого узел отправляет несколько «сообщений», то на уровне приложения должен быть какой-то индикатор сообщений, например, префикс каждого сообщения длиной (как в TLS), заканчивая каждое сообщение новой строкой (например,сделано в SMTP) или аналогичный.Затем получателю необходимо прочитать данные в соответствии с форматом сообщения, например сначала прочитать длину, а затем заданное количество байтов.

...