问题
The goal which I am attempting to achieve is for a client to send the following command to a server:
echo "Hello" | nc IP Port
Upon receiving the "Hello" keyword, the server which is listening using:
nc -nlp port
should then send a response "Holla" back to the client. I have tried the following, none of which work in my instance:
- run a command conditionally with netcat and grep
- Is a conditional response possible with netcat
- How to respond conditionally based on the request when using netcat
So the issue which I am currently facing is that upon receiving the "Hello" from the client side, the server side is unable to send a "Holla" response back to the client. Is there a way to do this with netcat? If so what am I missing?
Any help would be greatly appreciated.
回答1:
You'll need some bash
magic and some FIFO to achieve that, but it's totally doable:
#!/bin/bash
# Communication diagram:
#
# +----------+ +------------+
# | | stdout | |
# | nc | =======> | _feed_fifo |
# | | | |
# +---stdin--+ +------------+
# /\ ||
# || || $fifo_ref
# || \/
# +--stdout----------stdin-+
# | |
# | __handle_fifo_data |
# | |
# +------------------------+
fifo_ref="$RANDOM.fifo"
running_lock="$RANDOM.run"
# Strip leading and trailing white space (new line inclusive).
trim() {
[[ "$1" =~ [^[:space:]](.*[^[:space:]])? ]]
printf "%s" "$BASH_REMATCH"
}
# Handles data coming from the nc, with it's stdout connected
# directly to the client.
__handle_fifo_data() {
# Keep trying to read the fifo while it exists
while test -e "$1"
do
while read -r line
do
# This is where the magic happens. Anything sent to stdout will
# be transmitted to the client connected to the nc
echo "handling $line" >&2 # this is how we debug what's coming
# Lines will include a \r in the end if coming from telnet.
# Stripping the line from unwanted characters in the beginning/end
# (line breaks, spaces, etc).
message="$(trim "$line")"
# Responding only if the message is "Hello"
[ "$message" == "Hello" ] && {
echo "Hola!"
}
done < $1 # feeding the loop with our fifo
done
}
# Will read input and feed the fifo so we can handle data
__feed_fifo() {
# This is important, otherwise we'll trash the terminal with lots of
# bash pids trying to read a dead stdin
while test -e "$1"
do
# Testing again in case of concurrency
test -e "$1" && cat - > "$1"
done
}
# Cleaning up if something goes south or the program simply ends
trap "rm -rf ${fifo_ref} ${running_lock}" EXIT INT TERM HUP
# Let's get this party started
touch "$running_lock"
# Won't stop until you say so
while test -e "$running_lock"
do
# Let's clear out the fifo so we don't get dirt from previous connections
test -e "${fifo_ref}" && rm -rf "${fifo_ref}"
mkfifo "${fifo_ref}"
# Netcat port 9999
# We'll feed the nc using our __handle_fifo_data and read from it to a
# __feed_fifo which will try to keep stdin open all the time, feeding
# __handle_fifo_data
nc -l 9999 \
0< <(__handle_fifo_data "${fifo_ref}") \
1> >(__feed_fifo "${fifo_ref}")
done
You can test it by saving it to something like server.sh
and running in one session:
$ bash -x ./server.sh
handling Hello
And in other session:
$ telnet localhost 9999
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Hello
Hola!
^]
telnet> Connection closed.
To stop it just ^C
来源:https://stackoverflow.com/questions/44900864/netcat-bidirectional-communication