Вопрос или проблема
Я использую socat для маршрутизации последовательного ввода через сеть, чтобы управлять устройством Arduino через виртуальный COM-порт.
Моя команда для запуска socat выглядит так:
socat /dev/serial0,b500000,raw,echo=0 TCP-LISTEN:9876,nodelay,fork&
Это работает в первый раз, когда устройство подключается к порту :9876, все проходит отлично. Однако, если соединение сбрасывается с другой стороны (которая использует com2tcp на Windows), любые дальнейшие подключения будут передавать данные по сети на RasPi, хостящую socat, и выводить их на последовательное устройство, но данные не будут принимать из /dev/serial0. Мне нужно убить оригинальный процесс socat, подождать, пока порт освободится, и затем снова запустить socat. Поскольку RasPi работает без экрана, это неприятность, которую я бы предпочел избежать.
Есть ли способ разрешить несколько несинхронных соединений работать таким образом? Я предполагаю, что есть какая-то настройка, которую нужно ввести после echo=0
, но я не могу понять, какая именно.
(Дополнительные заметки: скорость 500000 бод необходима, так как это скорость, требуемая для программного обеспечения, которое я использую, называемого GIMX. Цель этой настройки — подключиться к игровой консоли с устройствами в другой комнате, используя функционал удаленной игры для игры. Я установил эту команду в /etc/rc.local
, чтобы запускать socat при загрузке, так как RasPi также используется как медиаплеер с Volumio; это просто работает в фоновом режиме.)
ИЗМЕНЕНИЕ: Я в конечном итоге отказался от маршрута socat/com2tcp и внедрил соединение, соответствующее RFC2247. Это означало, что мне не нужно было беспокоиться о ручной настройке скорости передачи, и, похоже, оно работает более стабильно. Я основывал это на информации из https://robosavvy.com/forum/viewtopic.php?t=7578, которая в основном дает полное представление о том, как это настроить. Хотя несколько ссылок мертвы, в ней есть необходимая информация для установления соединения.
Я полагаю, что команда, которую я искал, была “end-close”, однако я не тестировал это перед тем, как перейти на новую настройку.
На локальной сети вы, вероятно, захотите использовать UDP вместо TCP. Вы получите лучшую задержку, и проблема с соединением, вероятно, исчезнет. Быстрый поиск приводит к программе под названием COM2UDP.
Ответ или решение
Тема: Решение проблемы с многократными попытками подключения через socat в проектах с Arduino
Ваша проблема с использованием socat для маршрутизации последовательного ввода через сеть на Raspberry Pi, связанная с управлением устройством Arduino, является распространенной среди разработчиков, работающих с удаленными последовательными устройствами. Рассмотрим ваше текущее решение и возможные пути оптимизации.
Описание проблемы
Вы используете следующую команду для запуска socat:
socat /dev/serial0,b500000,raw,echo=0 TCP-LISTEN:9876,nodelay,fork&
Эта команда корректно работает при первом подключении к порту 9876, однако, если соединение обрывается, вы сталкиваетесь с тем, что дальнейшие подключения не обеспечивают двустороннюю связь: данные передаются из сети на Raspberry Pi и далее на последовательный порт, но данные не принимаются с /dev/serial0. Вы должны завершать процесс socat, чтобы освободить порт, что создает неудобства в работе с headless Raspberry Pi.
Предложенное решение
Для решения вашей проблемы существует несколько подходов, которые могут включать изменения в настройках socat:
-
Разрешение повторного использования сокетов:
Вы можете добавить опциюSO_REUSEADDR
к вашей команде socat. Эта опция позволит повторно использовать адреса и порты, что может помочь вам избежать необходимости перезапуска socat после разрыва соединений. Соответствующая команда будет выглядеть так:socat /dev/serial0,b500000,raw,echo=0 TCP-LISTEN:9876,nodelay,fork,bind=0.0.0.0,reuseaddr&
-
Использование опции
end-close
:
Как вы сами упомянули, опцияend-close
может помочь вам в управлении завершением соединений. Эта опция закрывает все открытые соединения, связанные с сокетом, когда одно из них закрывается. Добавьте ее в вашу команду:socat /dev/serial0,b500000,raw,echo=0 TCP-LISTEN:9876,nodelay,fork,end-close&
-
Переход на более надежный протокол:
Если вы уже пробовали использовать более сложные настройки, рассмотрите возможность использованияCOM2UDP
, как упомянуто в вашем обсуждении. Протокол UDP может обеспечить более низкую задержку и отсутствие проблем с поддержанием соединения. Это может оказаться более эффективным для приложения, работающего в локальной сети. -
Упрощение настройки и дополнительные библиотеки:
Для долгосрочного решения вы также можете рассмотреть использование специализированных библиотек, таких какrfc2217
, которые обеспечивают надежное управление портами, не требуя от вас глубокого понимания сетевых деталей.
Заключение
Ваш текущий подход к использованию socat является хорошим, однако в нем есть возможности для улучшения, которые могут усилить его эффективность и устранить проблемы с управлением подключениями. Попробуйте включить предложенные изменения и протестируйте их в вашей среде. Это должно позволить вам избежать необходимости вручную перезапускать socat и улучшить взаимодействие с вашими устройствами.
Надеюсь, эти рекомендации окажутся полезными для дальнейшего упрощения вашего проекта с Arduino и Raspberry Pi.