Проектирование сети для управления Raspberry Pi из Windows - PullRequest
0 голосов
/ 04 сентября 2018

Я создаю приложение, которое управляет с моего компьютера (Windows 7) некоторыми другими приложениями, запущенными на удаленном Raspberry Pi. Я создал сервер, используя winsock на стороне Windows. В настоящее время сервер получает видеопоток, записанный с Raspberry Pi. Клиентская сторона (Raspberry Pi) написана на Python 3 с использованием сокета. Он захватывает видео, выполняет некоторые операции, затем сжимает его в файл JPEG с переменным качеством и отправляет его на сервер, который в настоящее время принимает, переводит, распаковывает и отображает изображения.

К настоящему времени сервер «повторяет» полученную информацию, чтобы подтвердить ее, но я считаю, что в этом нет необходимости, на самом деле она может быть неэффективной. Но когда я переключаю эхо на ACK (строка «ОК» в байтах), я не испытываю никакого улучшения производительности программы. Это работает хуже, с многими изображениями, полученными неправильно (без надлежащего завершения этих изображений => потерянные пакеты), и время выполнения не затрагивается. Я знаю, что, в зависимости от структуры соединения, меньшие пакеты не означают лучшей производительности ... Еще хуже, мои ACK автоматически упаковываются вместе, потому что их размер очень мал, и это может вызвать некоторые неправильные действия, такие как активное ожидание (я думаю, это происходит из-за стратегии отложенного ACK и / или алгоритма Nagle), взаимной блокировки, если клиент не получает ACK и продолжает ждать в цикле while и т. д.

Читая некоторую документацию по TCP / IP, я увидел, что для моего приложения для потоковой передачи данных есть некоторые рекомендации, и я хотел бы проверить здесь, прав ли я и как построить свою структуру:

  1. Должен ли я создать 2 соединения?: одно для потоковой передачи данных (видео), а другое для обмена сообщениями или командами (например, параметры или команды, которые должны выполняться удаленно). Поскольку для потоковой передачи данных требуется самая широкая доступная пропускная способность, в то время как требования к выполнению команды используют небольшую передачу данных. Поэтому оба соединения будут установлены по-разному.
  2. Буферы отправки нулевой длины и отправка блокировки: Я прочитал здесь что " Не отключайте буферизацию отправки, если вы не учли влияние во всех сетевых средах Единственное исключение: потоковая передача данных с использованием перекрывающегося ввода-вывода должна устанавливать буфер отправки на ноль". Если я использую одно соединение, я должен отключить буферизацию отправки на стороне winsock? А как насчет сокета Python 3?
  3. Есть ли преимущество удаления эха: Я передаю через WiFi, и я не уверен, влияет ли эхо-сигнал с сервера на производительность сети, потому что, возможно, по умолчанию есть некоторые пропускная способность, зарезервированная для отправки, и некоторая другая для получения (выгрузка / загрузка), которая не перебалансируется при отсутствии загружаемого трафика ... Если я не улучшу производительность, я бы оставил эхо, как сейчас, так как работает плавно.
  4. Какой-нибудь совет или рекомендация для моей структуры сети, которая мне не хватает?

Сводка Python:

self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.server_address = ("some_ip_address", portNumber)
self.sock.connect(self.server_address)
#...
self.sock.send(data)
recsize = 0
expsize = len(data) #echo strategy
while recsize < expsize:
    recv = self.sock.recv(self.buffLEN)
    recsize += len(recv)

Создание Winsock:

ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
hints.ai_flags = AI_PASSIVE;
getaddrinfo(NULL, DEFAULT_PORT, &hints, &result);
ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
bind(ListenSocket, result->ai_addr, (int)result->ai_addrlen);
freeaddrinfo(result);
listen(ListenSocket, SOMAXCONN);
ClientSocket = accept(ListenSocket, NULL, NULL);

Метод «Прием и эхо»:

recv(ClientSocket, recvbuf, recvbuflen, 0);
//does some stuff with information recieved
// Echo the buffer back to the sender
send(ClientSocket, recvbuf, iResult, 0);

Чтобы сделать это как ACK: Изменения Python:

expsize = len(b"OK")

C ++ изменения:

#define ACK "OK"
//...
send(ClientSocket, ACK, (int)strlen(ACK), 0);

Сторона Python не так хорошо работает, потому что полученный пакет содержит несколько b "OKOKOKOK ...", поэтому ожидается, что "len" обычно не совпадает с was.

Итак, я изменился на:

while True:
    received = self.sock.recv(self.bufferLEN)
    if (str(recv)).find(str(b"OK")) != -1:
        break

Но это изменение по-прежнему не работает (многие пакеты теряются на стороне сервера => неполные образы, производительность не улучшается и т. Д.)

Заранее благодарю за помощь и комментарии, и я надеюсь, что этот пост будет полезен для кого-то еще!

С уважением

...