19

For testing purposes I need to create a shell script that connects with a remote IP>Port and sends a simple text TCPIP Socket message.

22

Using nc (netcat).

Server:

$ nc -l localhost 3000

Client:

$ nc localhost 3000

Both server and client will read and write to standard output/input.

This will work when both server and client is on the same machine. Otherwise change localhost to the external name of the server.

Slightly more interesting, a "server" that gives you the time of day if you connect to it and send it a d, and which quits if you send q:

Server (in bash):

#!/bin/bash

coproc nc -l localhost 3000

while read -r cmd; do
  case $cmd in
    d) date ;;
    q) break ;;
    *) echo 'What?'
  esac
done <&"${COPROC[0]}" >&"${COPROC[1]}"

kill "$COPROC_PID"

Client session:

$ nc localhost 3000
d
Thu Jan 12 18:04:21 CET 2017
Hello?
What?
q

(the server exits after q, but the client doesn't detect that it's gone until you press Enter).

  • 2
    If the server returns a result when client finishes sending data, the ctrl+c won't show the result. If using echo, e.g. echo "cookie" | nc localhost 9090, the client's output stream will be closed (eof sent) but the client will still wait for the server's result. – AlikElzin-kilaka Jul 17 '18 at 10:38
13

In general advice with netcat is better way.

But in bash and ksh you can also do this:

exec 3<>/dev/tcp/hostname/port
echo "request" 1>&3
response="$(cat <&3)"
  • what is 1>&3 ? I am not sure what that represents – Alexander Mills Apr 20 '18 at 21:54
  • in other words, why not just echo "request" >&3, I guess the 1 is just redundant – Alexander Mills Apr 20 '18 at 21:55
  • This might be better with an example. – Ken Sharp Mar 3 at 0:07
4

try netcat (e.g. nc )

echo GET / HTTP/1.0 | nc 0 80
HTTP/1.1 400 Bad Request
Date: Thu, 12 Jan 2017 13:44:23 GMT
Server: Apache/2.4.18 (Ubuntu)
Content-Length: 311
Connection: close
Content-Type: text/html; charset=iso-8859-1
  • in sample above I send a GET (echo GET / HTTP/1.0 ) to my local http server
  • If you don't want complex protocol, this might do the job.
1

In many cases I have not had access to netcat/socat. I have also had issues with using bash's exec in a distributed computing environment.

Due to its prevalence, an alternative solution is to use GNU AWK's TCP/IP capabilities. It provides a simple syntax based around it's "two-way pipe" operator.

Here is a modified example from this source that will send a TCP message over a socket:

BEGIN {
 NetService = "/inet/tcp/0/cs.wisc.edu/finger"
 print "coke" |& NetService
 close(NetService)
}

The full syntax for the address is: /net-type/protocol/local-port/remote-host/remote-port. When local-port is set to 0 the local host chooses the port automatically which is typically what you want. You can read more about gawk's TCP/IP networking capabilities in the supplied link.

It's worth noting that this can be shortened if you're only going to be sending one message per awk execution:

BEGIN {print "coke" |& "/inet/tcp/0/cs.wisc.edu/finger"}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.