I've written a small UDP server in PHP which listens on a socket, accepts a command, and performs an action. It's really quite basic. I can connect to it manually like this:
% nc -u host port (where nc = Ncat: Version 7.50 ( https://nmap.org/ncat ))
As I enter commands, I see the resulting response. It works exactly the way I want it to work from the command line.
However, if I simply "cat" a file in like this:
cat FILE| nc -u host port or send it data like this:
echo "command1\ncommand2\n" | nc -u host port ... then my PHP app reads everything including the end of line characters all at once. I only want to read up to the end of the line.
Sure, I could wrap around the contents of the file, and send each line to nc:
for x in `cat <file>`; do echo $x | nc -u host port done ... but that's a complete waste. I want 1 connection to nc, not many.
The EOL characters make it into the string because when I print the output in the PHP app, I see: command1 command2 ... but it's all in one string.
Why is the interactive mode behaving differently than the non-interactive mode?
I've been experimenting all afternoon, and I can't seem to make this work.
I'm sure there's an explanation though.
Thanks for any information you can provide.
PS: The basics of the PHP code is:
$sock = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP); socket_bind($sock, '0.0.0.0', 2000); for (;;) { socket_recvfrom($sock, $cmd, 1024, 0, $ip, $port); echo "command is $cmd"; $reply = process($cmd); echo "reply is $reply"; socket_sendto($sock, $reply, strlen($reply), 0, $ip, $port); } While entering text with nc interactively, you can hit CTRL-D to separate packets. If I do the same thing in a shell script:
printf 'command1\0014commandd2\0014'| nc -u host port ... the commands all appear as one command.
If I reduce the packet size in the PHP code to say, 5, then send data that is 20 bytes long, the data is truncated, and not separated.
I've also ready online this could be a buffering issue. I tried using:
stdbuf -oL -eL cat FILE | nc -u host port ... but that surprisingly didn't make a difference either.
Finally, I have discovered that if I do:
for x in command1 command2; do echo $x sleep 1 done | nc -u host port ... that everything goes as planned. The server receives the first command, then the second command.
What isn't clear really is why the sleep 1 makes a difference. Take it out, and it fails. The above is certainly better than sending each echo to nc.