socat espera respuesta

socat espera respuesta

Yo uso esto en un script

echo $(echo "sign 00:07:32:46:04:75" | socat UDP4-DATAGRAM:239.192.0.2:9000 -)

pero esto se detiene inmediatamente y no recibo respuesta del servidor

si lo hago

echo $(echo "sign 00:07:32:46:04:75" | socat -t5 UDP4-DATAGRAM:239.192.0.2:9000 -)

Siempre espera 5 secondstambién cuando la respuesta esté disponible después de 1 segundo.

¿Hay alguna manera de detener el comando inmediatamente después de recibir el primer mensaje?

Respuesta1

Suponiendo que la respuesta es una línea de texto delimitada por una nueva línea, con bash, siempre puedes hacer:

IFS= read -r answer < <(
  echo 'sign 00:07:32:46:04:75' |
    socat -t 5 - UDP4-DATAGRAM:239.192.0.2:9000)

Eso regresará tan pronto como haya una respuesta y socatse dejará ejecutándose en segundo plano durante el tiempo restante.

En zsh, necesitaría agregar un &al final de la echo|socatcanalización para que no tenga que esperar. Es posible que desee agregarlo bashtambién para estar preparado para el futuro en caso de que bashdecida cambiar el comportamiento en el futuro.

Si la respuesta puede tener más de una línea o no está delimitada por una nueva línea, podrías zshhacer:

zmodload zsh/system
(echo 'sign 00:07:32:46:04:75' |
  socat -t 5 - UDP4-DATAGRAM:239.192.0.2:9000 &) | sysread answer

El sysreadincorporado lo haceuno read()llamada al sistema de tamaño 8192. Eso supone socatque escribe la respuesta en la tubería enuno write()llamada al sistema (lo cual hace).

Portablemente, siempre puedes recurrir a ddeso:

answer=$(
  (echo 'sign 00:07:32:46:04:75' |
    socat -t 5 - UDP4-DATAGRAM:239.192.0.2:9000 &) |
    dd bs=8192 count=1 2> /dev/null
)

(tenga en cuenta que la sustitución de comandos elimina todos los caracteres de nueva línea finales).

Si quieres evitar socatquedarte esperando esos segundos adicionales después de eso, puedes hacer algo como:

answer=$(
  (echo 'sign 00:07:32:46:04:75' |
    sh -c 'echo "$$"
           exec socat -t 5 - UDP4-DATAGRAM:239.192.0.2:9000 &
  ) | {
    IFS= read pid
    dd bs=8192 count=1 2> /dev/null
    kill -s PIPE "$pid"
  }
)

información relacionada