Я пытаюсь отправить данные с одного raspberry pi (4) на другой pi (0 w) (я включаю устройства, потому что w 0 не самое мощное устройство, оно немного медленное при запуске рабочий стол, но я не уверен, что это проблема). Передача обычно работает, но время от времени я теряю сообщение. Я полагаю, что могу добавить дополнительный шаг, чтобы убедиться, что сообщение прошло, и запросить его снова, если нет (например, вставлять каждое сообщение некоторое время l oop, чтобы сравнить числа счетчиков), но я не был уверен, было ли лучший путь. Ниже показан некоторый фиктивный код для иллюстрации проблемы.
Клиент (raspberry pi 4)
#client
import socket
import time
import pickle
import random
HOST = '192.168.1.37'
PORT = 2031
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
counter = 0
while True:
counter += 1
message = ['note_off', 21, counter, time.time()]
message_2 = pickle.dumps(message)
print(message)
s.send(message_2)
time.sleep(random.random() / 10)
Сервер (raspberry pi 0 w)
# server
import socket
import pickle
import time
import threading
HOST = '192.168.1.37'
PORT = 2031
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
s.listen(1)
global stop
stop = False
def testa():
counter = 0
conn, addr = s.accept()
s.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
print('Connected by', addr)
try:
while True and not stop:
message_2 = conn.recv(1024)
message = pickle.loads(message_2)
if message:
counter += 1
print('counter = {}, message = {}'.format(counter, message))
s.close()
except:
print('closing')
s.close()
try:
print('creating thread')
test_thread = threading.Thread(target=testa)
print('starting thread')
test_thread.start()
print('thread started')
except:
s.close()
stop = True
Итак, в клиентский код, я запускаю счетчик и включаю его в часть сообщения, а также запускаю дублирующий счетчик в другой программе, чтобы мы могли сравнить. Я печатаю вывод для проверки.
counter = 1, message = ['note_off', 21, 1, 1585259341.171993]
counter = 2, message = ['note_off', 21, 2, 1585259341.2157793]
...
counter = 27, message = ['note_off', 21, 27, 1585259342.608451]
counter = 28, message = ['note_off', 21, 28, 1585259342.6267097]
counter = 29, message = ['note_off', 21, 31, 1585259342.739835]
counter = 30, message = ['note_off', 21, 32, 1585259342.813044]
counter = 31, message = ['note_off', 21, 33, 1585259342.8884292]
...
counter = 230, message = ['note_off', 21, 267, 1585259354.8655927]
counter = 231, message = ['note_off', 21, 268, 1585259354.9502656]
counter = 232, message = ['note_off', 21, 269, 1585259354.999945]
Счетчик, а затем третий элемент message
должен совпадать, и они некоторое время это делают, но затем сообщения начинают сбрасываться.
Примечание: во время написания этого я понял, что не устанавливал параметры сокета в клиентском коде. Я запустил его снова с этой опцией и получил те же результаты (пропущенные сообщения). Не уверен, что это уместно, или мне нужен этот фрагмент кода, но я подумал, что должен упомянуть об этом.
РЕШЕНИЕ Как указано в комментариях, это было результатом Мое недопонимание, как именно работает поток (я думал об этом как о потоке сообщений, когда это действительно поток байтов). В моем случае, поскольку я точно знаю, насколько большими будут объекты, которые будут отправлены, я могу установить параметр для recv
, чтобы он точно определял количество отправляемых байтов (есть более элегантные решения, но этот работает для моего случая).