С учетом комментариев у меня есть догадка о , скорее всего, проблема, но есть, по крайней мере, 50% шанс, я догадался неправильно, и в этом случае ... скажите мне, и я удалю ответ.
Я предполагаю, что вы пытаетесь использовать сокет потока, как если бы это была последовательность сообщений. Это очень распространенная проблема среди новичков сетевого программирования.
Представьте отправителя делает что-то вроде этого:
data = pickle.dumps(object);
self.sock.sendall(data)
И приемник делает что-то вроде этого:
data = self.sock.recv(4096)
self.object = pickle.loads(data)
Это может работать 99% времени в простых тестах, но в реальном масштабе использование в мире не сработает. Вы получите частичные сообщения или несколько сообщений в одном вызове или какую-нибудь забавную комбинацию из вышеперечисленного (например, половину сообщения 2, все сообщение 3 и третье сообщение 4).
Итак, вы передадите частичное сообщение на номер loads
и вернетесь с сообщением о том, что это не полный рассол.
Это не потому, что что-то сломано; вот как это предположительно для работы. Сокет (TCP) представляет собой поток : последовательность байтов, а не последовательность сообщений. Любая структура, которую вы хотите, помимо этого, вы должны встраивать в данные.
Это означает, что вам необходимо разработать и реализовать протокол, чтобы узнать, когда будет завершено каждое сообщение. Простейшие протоколы - это, вероятно, строки (очевидно, полезны только в том случае, если сообщение никогда не может иметь невыбранную новую строку) и netstrings, но все, что дает вам однозначный способ взглянуть на некоторые данные и сказать «Это сообщение 0, это сообщение 1 и т. Д. «. будет работать.
Обычно это означает добавление полученных данных в некоторый буфер и циклическое перемещение сообщений в этом буфере. Например, с линиями, вместо этого:
while True:
line = sock.recv(4096)
do_stuff(line)
... вам это нужно:
rdbuf = ''
while True:
rdbuf += sock.recv(4096)
lines = rdbuf.split('\n')
rdbuf = lines[-1]
for line in lines[:-1]:
dostuff(line)
Если вы думаете об этом, это ничем не отличается от файла. Представьте себе этот код:
with open('foo.data', 'wb') as f:
f.write('123')
f.write('45')
with open('foo.data', 'rb') as f:
while True:
number = f.read()
Это будет читать '12345'
, а не '123'
.Если вы хотите получить '123'
, вам нужно знать, как читать только 3 байта. Приклеивание префикса длины или добавление пробелов в качестве разделителя или просто наличие внешних знаний о том, что первое число всегда равно 3 цифрам ... ничего работает, но вам нужно сделать что-то.
Вы уверены, что получили все байты для рассола на принимающем потоке? –
@Martijin Pieters Вы предлагаете, я должен поставить вызов сна перед травлением, чтобы дать достаточно времени для поступления всех байтов? –
Я предлагаю вам убедиться, что все данные были получены до передачи функции 'pickle.loads'. –