Клиент Modbus TCP закрывает соединение из-за непредвиденного ответа от реализации моего сервера - PullRequest
0 голосов
/ 14 марта 2012

Я реализовал Modbus через TCP в качестве серверного программного обеспечения на Python.Приложение является многопоточным и сильно зависит от стандартных библиотек.У меня проблемы с управлением соединением на стороне сервера.Между тем моя реализация в качестве Modbus поверх TCP в качестве клиента работает просто отлично.

Описание реализации

  • Сервер многопоточный, один поток управляет сокетом SOCK_STREAM для получения кадров
  • select используется из соображений эффективности
  • Семафор используется для предотвращения одновременного доступа к ресурсам сокета при отправке или получении
  • Инкапсуляция верхнего уровня Modbus выполняется прозрачно с помощью методов отправки и получения, этоВ любом случае, только вопрос построения фрейма с правильным заголовком и полезной нагрузкой ...
  • Запускаются другие потоки, внутри него вызываются методы отправки и получения Modbus.

Контекст TCP

TCP запущен и работает, привязан к порту, настроен на максимальное количество клиентов и прослушивается.

Трассировки в wireshark show:

  • Клиент: SYN
  • Мой сервер приложений: SYN, ACK
  • Клиент: ACK

На стороне сервера был создан совершенно новый сокет какожидается и привязан к клиентскому сокету.

Пока все хорошо.

Контекст Modbus

  • Клиент: Отправить кадр Modbus,Флаги TCP = 0x18, что означает ACK + PUSH
  • Мой сервер приложений: Не ожидает и отправляет один пустой кадр TCP ACK .
  • Клиент: Ожидание кадра Modbusс флагом tcp ack.Поэтому он принимает это за ошибку и просит закрыть соединение.

Следовательно, мое серверное программное обеспечение не может отправить какой-либо фактический ответ впоследствии, так как сокет на стороне клиента закрыт или уже закрыт.

Моя проблема

  • Я получаю кадр Modbus, который должен обработать основной поток (на стороне сервера)
  • Обработка занимает несколько мс, в то время как TCP ACKфрейм отправляется через сокет моего сервера, тогда как я бы не хотел ничего отправлять!

Есть ли у вас какие-либо идеи о том, как управлять поведением ACK?Я читал материал об алгоритме naggle, но, похоже, он не входит в сферу проблемы здесь ... Я не уверен, что какой-либо вариант метода setsockopt решит и мою проблему, но я могу ошибаться.

Если у вас есть предложения, я очень заинтересован ... Надеюсь, я достаточно ясен.

1 Ответ

0 голосов
/ 14 марта 2012

Кажется странным требованием, чтобы все пакеты TCP содержали полезную нагрузку, так как это очень сложно контролировать, если вы не интегрированы со стеком TCP. Если это действительно тот случай, когда клиент падает, потому что ACK не имеет полезной нагрузки Modbus, я думаю, что единственное, что вы можете сделать из python, это попробовать отключить опцию сокета TCP_QUICKACK, чтобы TCP ждал 500 мс перед отправкой ACK. Это, очевидно, не будет работать во всех случаях (или может вообще не работать, если для создания ответа ваш код> 500 мс), но я не знаю никаких других опций, использующих API сокетов из python.

Этот SO-ответ расскажет, как его отключить: Отключить задержанные TCP ACK . Должно быть легко понять, как это сделать. Обратите внимание, вам необходимо постоянно включать его после получения данных.

...