Почему цикл Python TCP-получатель получает сообщение частично? - PullRequest
1 голос
/ 04 апреля 2020

У меня есть сервер, который отправляет некоторые сообщения клиенту. Оператор print (trades) показывает, что программа чтения файлов правильно читает весь файл csv:

    def send_past_trades(self):
        with open('OTC_trade_records.csv',newline='') as f:
            connectionSocket, addr = self.client
            trades = f.read()
            #print(trades)
            connectionSocket.send(trades.encode())

Мой клиентский приемник выглядит так:

msg = b""
while(True):
    print("Batch receiving")
    tmp = client_socket.recv(4096)
    msg += tmp
    if len(tmp) < 4096:
        print(len(tmp))
        break
msg = msg.decode()
print(msg)

Сообщение всегда частичное. Я вижу, что оператор «Пакетный прием» печатается один раз, и когда оператор прерывания инициируется, длина последнего сообщения составляет 1228.

Другой момент заключается в том, что этот код прекрасно работает в моей локальной системе. Проблема возникает, когда я помещаю серверную программу на удаленный сервер. Существует ли вероятность того, что сервер вмешается в сообщение?

Примечание. Я пробовал разные способы решения проблемы, такие как отправка только сообщений размером 1024b в al oop. Все еще частичные сообщения получены.

1 Ответ

1 голос
/ 04 апреля 2020

Проблема здесь:

if len(tmp) < 4096:
    print(len(tmp))
    break

Дело в том, что bufsize in recv(bufsize) - максимальный размер для получения. recv вернет меньше байтов, если их будет меньше.

Я предлагаю определить простой протокол связи, который описывает структуру сообщения с заголовком и полезной нагрузкой. Заголовок должен содержать размер полезной нагрузки. Это позволяет вам анализировать данные из входящего потока TCP и получать точный размер полученных данных. Затем вы можете получить запрошенный объем данных.

Клиент будет выглядеть так:

import struct

# Receive a header
header = connection.recv(8)
(length,) = struct.unpack('>Q', header)  # Parse payload length

# Receive the payload
payload = b''
while len(payload) < length:
    to_read = length - len(payload)
    payload += connection.recv(4096 if to_read > 4096 else to_read)

Сервер:

import struct

with open('OTC_trade_records.csv',newline='') as f:
    connectionSocket, addr = self.client
    trades = f.read()
    length = struct.pack('>Q', len(trades))
    connectionSocket.sendall(length)
    connectionSocket.sendall(trades)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...