SOKAT и проблемы с чтением из серийного порта
Работаю с неким проприетарным протоколом. Ранее для общения с сервером пользовался tcp/ip сокетом и было все замечательно. Сейчас же клиент находится на той-же машине что и сервер и как следствие общение происходит уже через serial_port. Для того чтобы не переписывать код, использовал вот такую команду:
/usr/bin/socat file:/dev/ttyUSB3,raw,echo=0 tcp-listen:42616,reuseaddr,fork
Команда перенаправляет ввод\вывод в сокет и у меня все заработало. Однако же при тесте выявил проблему, когда я например посылаю команду и ребутаю приложение и подключаюсь снова, то в "сокете" остаются старые сообщения от сервера. Это очень мешает, так как при посылке команды А я должен получать ответ А1, при команде B должен получать ответ B1 и т.д. Протокол чисто бинарный и нет возможности определить на какую команду какой ответ. Вопрос: можно ли настроить socat таким образом, чтобы он при коннекте\дисконекте делал close серийного порта или просто очищал все данные?
Ответы (1 шт):
Просто поменяй местами адреса, ещё добавил бы max-children=1
/usr/bin/socat tcp-listen:42616,reuseaddr,fork,max-children=1 file:/dev/ttyUSB3,raw,echo=0
Тогда ttyUSB3 порт будет открываться после подключения клиента, закрываться при отключении.
П.С. Но у этого есть небольшая побочка которая случается редко ( и не должна случаться на локалхосте ): если конект не порвался по fyn, то сокат висит как зомби и не отдает порт.
Сейчас использую маленькую программку на python вместо socat:
import asyncio
import serial_asyncio
import sys
class Output(asyncio.Protocol):
def connection_made(self, transport):
self.transport = transport
self.tcp = None
transport.serial.rts = False
def data_received(self, data):
print('>', data)
self.time = self.loop.time()
if self.tcp:
self.tcp.write(data)
def connection_lost(self, exc):
sys.exit(1)
def pause_writing(self):
print(self.transport.get_write_buffer_size())
def resume_writing(self):
print(self.transport.get_write_buffer_size())
def set_tcp(self, transport):
if self.tcp:
self.tcp.close() # отключает старого клиента
self.tcp = transport
self.tcp.resume_reading()
class ProxyServerProtocol(asyncio.Protocol):
def __init__(self, serial):
self.serial = serial
def connection_made(self, transport):
peername = transport.get_extra_info('peername')
self.transport = transport
transport.pause_reading()
self.serial.set_tcp(transport)
def data_received(self, data):
print('<', data)
self.serial.transport.write(data)
async def main():
loop = asyncio.get_event_loop()
serial_transpot, serial_protocol = await serial_asyncio.create_serial_connection(
loop,
Output,
sys.argv[1],
baudrate=115200
)
server = await loop.create_server(
lambda: ProxyServerProtocol(serial_protocol),
'0.0.0.0', 5555)
return server
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
loop.run_forever()