How to continuously send data to client from server - bash

I want to continuously send data from server to client. On the client side, I only want the received data to be displayed. How to continuously send data to client?
echo "Hello, client!" | nc did not work.
Thanks in advance
You can see example script of server side below:
#!/bin/bash
while true
do
echo "Sending message to client..."
echo "Hello, client!" | nc <ip> <port>
done

Your nc command is missing -l (listen) parameter to behave as a server.
Try this:
#!/bin/bash
while true
do
echo "Sending message to client..."
echo "Hello, client!" | nc -l 10000
done
In another terminal, connect as a client as many times as you want and you'll see the message sent:
$ nc localhost 10000
Hello, client!
^C
$ nc localhost 10000
Hello, client!
^C
EDIT: To send messages to the client without needing to reconnect, you can create a fifo, make the server read this fifo continuously and forward this data to the client:
$ mkfifo fifo_toclient
$ tail -f fifo_toclient | nc -l 10000
Run the client side command as before:
$ nc localhost 10000
In another terminal and in the same directory, modify your script to write data to the pipe instead of directly to nc and run it:
$ cat send_to_client.sh
#!/bin/bash
while true
do
echo "Sending message to client..."
echo "Hello, client!" > fifo_toclient
sleep 1
done
$ bash ./send_to_client.sh
And you should see the messages in the output of the client side.

Related

How to compare output of slow netcat client with a file

readarray -t FILES < text.in
for ELEMENT in ${FILES[#]}
do
printf $ELEMENT
sleep 2
done | nc -q -1 localhost 5555
This code simulates a slow network client which sends a text line from text.in every 2 seconds to a key-value-store server with netcat.
How do I compare the output of netcat with a file test.out?
Example for text.in:
GET$5$hello
SET$5$hello$7$myworld
GET$5$hello
QUIT
Example for test.out:
ERR
OK
VALUE$7$myworld
Once the QUIT line is sent, the server closes the connection. After that I want to compare the standard output of netcat to test.out
I could do this: nc localhost 5555 < text.in | diff - test.out but then the entire file text.in is sent immediately which defeats the purpose of simulating a slow client.
I tried the following but it gets stuck and never returns anything:
readarray -t FILES < text.in
for ELEMENT in ${FILES[#]}
do
printf $ELEMENT
sleep 2
done | nc -q -1 localhost 5555 | diff - test.out
EDIT: ANSWER IN COMMENTS

How to close netcat connection after receive a server response?

I need to sendo a lot of messages via netcat or something similar. The problem is that when I run echo "something" | netcat ip port the connection continues opened after I received the response. Actually the connection continues opened waiting for a new input. However, what I need is that the connection closed after I receive the response. Look, my script is basically this:
#!/bin/bash
i=1
while [ $i -ne 10000 ];do
sed -n $[i]p wordlist | netcat localhost 30002 >> result
i=$[$i+1]
done
If I can close the connection after print the response in result, everything will work fine. I know that there is an option -w "x" that closes the connection after "x" seconds, but the minimum value for "x" is 1 and 1 is bigger than I can wait, I need close the connection as soon as possible.
Unfortunately, the -q flag didn't work for me.
I'm using "OpenBSD netcat (Debian patchlevel 1.187-1ubuntu0.1)" and, even though the -q flag shows up in the manual, it didn't work as mentioned in cnicutar's answer.
Therefore, my workaround was:
#!/bin/sh
# POSIX COMPLIANT
HOST="localhost"
PORT=30002
scan () {
# Ensuring there is no file named msg
rm msg
# While msg file doesn't exist or is empty, do
while [ ! -s msg ]; do
# Remove instruction from within the loop
rm msg
# Append the received messages to msg file, and put the process in the background
echo "$HOST $PORT" | xargs nc >> msg &
# If the file exists and is not empty, return, we received the message
[ -s msg ] && return;
# A small timeout.. doing some tests I noticed that a timeout of zero sometimes didn't work to catch the message
# Maybe nc needs a small time to receive everything. You might want to test and increase or decrease this timeout if needed.
sleep 0.1
# This script will be spawning a lot of nc process, to kill it before the loop runs again
pkill -x nc
done
} 2> /dev/null
scan
# The function returned, so cat the file
cat msg
# make sure nc is killed
pkill -x nc > /dev/null 2>&1
rm msg
What you're looking for is the -q switch. If you specify:
netcat -q 0 localhost 30002
netcat will exit immediately.

Read and write to the same netcat tcp connection

Say I write to a netcat connection:
tail -f ${file} | nc localhost 7050 | do_whatever | nc localhost 7050
what happens here is that we have two socket connections, to do some request/response. But that's not ideal for a few reasons.
What I am looking to do is reuse the same connection, to read from and write to.
Does anyone know how I can reuse just one netcat connection?
The correct way to do this in UNIX is to make use of a back pipe. You can do so as follows:
First, create a pipe: mknod bkpipe p
This creates a file named bkpipe of type pipe.
Next, figure out what you need to do. Here are two useful scenarios. In these, replace the hosts/addresses and port numbers with the appropriate ports for your relay.
To forward data sent to a local port to a remote port on another machine:
nc -l -p 9999 0<bkpipe | nc remotehost 7000 | tee bkpipe
To connect to another machine and then relay data in that connection to another:
nc leftHost 6000 0<bkpipe | nc rightHost 6000 | tee bkpipe
If you simply need to handle basic IPC within a single host, however, you can do away with netcat completely and just use the FIFO pipe that mknod creates. If you stuff things into the FIFO with one process, they will hang out there until something else reads them out.
Yeah, I think the simplest thing to do is use this method:
tail -f ${file} | nc localhost 7050 | do_whatever > ${file}
just write back into the same file (it's a 'named pipe').
As long as your messages are less than about 500 bytes, they won't interleave.
Using ncat is much easier and understandable for beginners as a one-liner ;)
prompt$> ncat -lk 5087 -c ' while true; do read i && echo [You entered:] $i; done'
Connect with telnet (or nc) to localhost port 5087, and everything you type echoes back to you ;)
Use -lk option for listening and keeping/maintaining (multiple) connections.
You can make one bash script out of it like this, using back slashes but it invokes multiple bash, not cheap on resource usage:
#!/bin/bash
# title : ncat-listener-bidirectional.sh
# description : This script will listen for text entered by a client
# like for instance telnet
# and echo back the key strokes
#
ncat -lk 5087 -c ' \
#!/bin/bash \
while true; do \
read i && echo [You entered:] $i; \
done'

Test if netcat listener got a connection and run a command locally

I need a way to fire a netcat listener from a shell script and if a connection received I need to run a command on the same local listener machine and without interrupting the netcat process / connection
it's like the -e option but I need to run a command locally while keeping the netcat connection running
I don't really know if it can be done I mean after the shell process forked the netcat child can it interact with nc's output for example and run other command before netcat exit?
Edit: I figured it's even easier to do it on the client C code side by checking the return value of an initial send() message to determine if the client connected successfully if we got the sent message length
sret = send(sock, message, strlen(message), 0);
if (sret == strlen(message)) // We're Connected
do something
Thanks
This will check if the initial nc process has started listening, and it will echo every line of input it receives and will then send back a Received response:
rm -f input.txt
touch input.txt
tail -f input.txt | nc -l 5555 > output.txt &
if ! ps -p $! >/dev/null; then
echo "Netcat didn't start. Exiting..."
exit 1
fi
tail -f output.txt | while read -r LINE; do
echo "Received input: $LINE"
echo "Received" >> input.txt
done
See if you can adapt this to meet your needs.

Bash script that accepts TCP connection, when a client connection occurs, send the time of day as a response to the client

I'm not going to lie this is an homework assignment, but I've been googling constantly to try to get some idea on how the heck to approach this particular question.
"Create a script named lab6s6 that accepts TCP connections. When a client connection
occurs, send the time of day as a response to client. You may choose any port number as
the listening port, and don’t forget to close your connections."
I'm running the latest fedora OS on my virtualbox
So far after doing some research I've come across this particular piece of code
$ exec {file-descriptor}<>/dev/{protocol}/{host}/{port}
What i've come up with after doing some research would be
exec 3<>/dev/TCP/127.0.0.1/8000
So from my general understanding the file descriptor tends to always be set to 3 (is this because of the stdin, stdout, stderr, what is the purpose of this?) also the "<>" which represents reading and writing, and the directory is a way to actually use those protocols. and lastly, for my ip I read somewhere that I shouldnt be using the loopback that this wouldn't work but I'll be honest I was a bit clueless while reading the article, and for the port I never really understood that, is it like the higher the number the more available your signal is?
and another side question, do I need to install any other type of software to even accomplish something like this? If anyone could clarify if I'm basically opening up like a phone line on my computer to be able to talk to other computers at are on my LAN, is that even possible?
I'm not asking for direct answers, but if someone could nudge me in the right direction I would appreciate it greatly!
Thanks again!
I have prepared for you two scripts: client and server
after giving them the execution right: chmod u+x script_name you can run them in any order (client -> server or server -> client)
bash_server.sh
#!/usr/bin/env bash
#define port on which the server will listen
#and the output file that will be used to store the client port to send an answer
readonly PORT_LISTEN=22222;
readonly SERVER_FILE=server_file_tmp.out;
echo "Removing the server temporary file: ${SERVER_FILE}";
rm -f "${SERVER_FILE}";
#will open/bind/listen on PORT_LISTEN and whenever some information is received
#it will write it in the SERVER FILE
echo "Starting the server on port: ${PORT_LISTEN} with configuration file: ${SERVER_FILE}";
nc -k -l "${PORT_LISTEN}" | tee "${SERVER_FILE}" &
echo "Waiting for connection..."
#active listening to entry connection
while true;
do
#get always information about the external connection trying to connect to our open port
tmpNetworkString=$(lsof -i:"${PORT_LISTEN}" | grep "localhost:${PORT_LISTEN} (ESTABLISHED)" | awk '{print $9}');
echo -n "${tmpNetworkString}";
if [ -s "${SERVER_FILE}" ] && [ ! -z "${tmpNetworkString}" ]; then
answerPORT=$(cat "${SERVER_FILE}");
echo "Connection received on port ${PORT_LISTEN}...";
incomingIP=$(echo $tmpNetworkString | cut -d':' -f1);
incomingPort=$(echo $tmpNetworkString | cut -d'-' -f1 | cut -d':' -f2);
echo ">>Incoming traffic IP: ${incomingIP}";
echo ">>Incoming traffic Port: ${incomingPort}";
echo "Answering on IP: ${incomingIP}, port: ${answerPORT}...";
#wait client port to be ready
nc -z "${incomingIP}" "${answerPORT}";
isOpen=$?;
while [ ! "${isOpen}" -eq 0 ];
do
nc -z "${incomingIP}" "${answerPORT}";
isOpen=$?;
done
echo $(date) | nc -q 2 "${incomingIP}" "${answerPORT}";
echo "Closing the server, port: ${PORT_LISTEN}";
fuser -k -n tcp "${PORT_LISTEN}";
echo "Removing the server temporary file: ${SERVER_FILE}";
rm -f "${SERVER_FILE}";
exit 0;
fi
done
bash_client.sh
#!/usr/bin/env bash
#define port on which the client will listen
#and the output file that will be used to store the answer from the server
readonly PORT_LISTEN=33333;
readonly CLIENT_FILE=client_file_tmp.out;
readonly SERVER_PORT=22222;
readonly SERVER_IP=localhost
echo "Removing the client temporary file: ${CLIENT_FILE}";
rm -f "${CLIENT_FILE}";
#will open/bind/listen on PORT_LISTEN and whenever some information is received
#it will write it in the CLIENT FILE
echo "Starting the server on port: ${PORT_LISTEN} with configuration file: ${CLIENT_FILE}";
nc -k -l "${PORT_LISTEN}" > "${CLIENT_FILE}" &
echo "Connecting to the server: ${SERVER_IP}, on port: ${SERVER_PORT} and waiting for answer";
#sending port information for answer:
#wait client port to be ready
nc -z "${SERVER_IP}" "${SERVER_PORT}";
isOpen=$?;
while [ ! "${isOpen}" -eq 0 ];
do
nc -z "${SERVER_IP}" "${SERVER_PORT}";
isOpen=$?;
done
echo "${PORT_LISTEN}" | nc -q 2 "${SERVER_IP}" "${SERVER_PORT}";
while true;
do
if [ -s "${CLIENT_FILE}" ]; then
echo "Answer received from server...";
echo "##############################";
echo "##############################";
cat "${CLIENT_FILE}";
echo "##############################";
echo "##############################";
#sleep 10;
echo "Closing the open port of the client, port: ${PORT_LISTEN}";
fuser -k -n tcp "${PORT_LISTEN}";
echo "Removing the answer file: ${CLIENT_FILE}";
rm -f "${CLIENT_FILE}";
exit 0;
fi
done

Resources