1. Overview
In this tutorial, we’ll learn how to receive information over a network port and print it to the terminal. First, we’ll use the nc command, also called netcat. Then, we’ll use a similar program called ncat developed by nmap. Finally, we’ll also learn we can use a special file in Bash to connect to a port.
2. Use Case
Sending and receiving information over a network port is useful when communicating between different computers. Sometimes, the communication is within the same computer using the local IP 127.0.0.1. When we use TCP to communicate over the network, the connection has a state. First, there has to be a process bound to a port and in a listening state. Then, another process attempts to connect to the port that the other process is listening to. Finally, once the connection is established, the processes can communicate with each other, and both sides of the connection can send and receive information. Therefore, when we want to receive and print the information that we receive on a port, we have to know if we need to listen or connect to that port. For instance, a program can write logs over the network instead of to a file. In this case, the process may connect to a port and write the logs through it. Alternatively, a process can listen to a port and write the logs to any other process that connects to that port. In the following sections, we’ll suppose there is a program on the same computer that runs continuously and logs the memory usage to port 9100.
3. Listening on a Port
If we want to listen on a port, we can use nc and configure it to listen on that port using the -l parameter. Then, we have to specify which port we want to bind to using the -p parameter followed by the port number. When we execute nc, it will run in the foreground, waiting for connections. When another process connects, nc will continue running and will print to the terminal everything it receives. Let’s run nc to listen on port 9100:
$ nc -l -p 9100
Sun Jan 14 14:34:00 -03 2022
total used free shared buff/cache available
Mem: 16311396 3642760 2523640 26792 10144996 12302388
Swap: 16777212 3096 16774116
Sun Jan 14 14:35:00 -03 2022
total used free shared buff/cache available
Mem: 16311396 3643252 2523140 26792 10145004 12301896
Swap: 16777212 3096 16774116
As we can see, nc listened on port 9100, and the other process connected and sent memory usage information. The nc command will terminate if the connected process ends, or if we press Ctrl+C. As nc prints the information to the standard output, we can pipe its output to another command. We can use tee as a t-splitter, so we can see the information and write it to a file at the same time. Let’s use tee to view the information, and write it to the memory_usage_logs.txt file:
$ nc -l -p 9100 | tee memory_usage_logs.txt
Sun Jan 14 14:42:00 -03 2022
total used free shared buff/cache available
Mem: 16311396 3870020 2291796 30904 10149580 12071016
Swap: 16777212 3096 16774116
^C
$ cat memory_usage_logs.txt
Sun Jan 14 14:42:00 -03 2022
total used free shared buff/cache available
Mem: 16311396 3870020 2291796 30904 10149580 12071016
Swap: 16777212 3096 16774116
Finally, we can use ncat instead of nc, and with the same parameters. ncat has additional functionality to support multiple connections using the -k parameter. This feature prevents ncat from exiting when the other process closes the connection. Instead, ncat keeps listening for new connections. Let’s run ncat to listen on port 9100, adding the -k parameter:
$ ncat -k -l -p 9100
Sun Jan 14 14:50:00 -03 2022
total used free shared buff/cache available
Mem: 16311396 4097840 2067580 26700 10145976 11847400
Swap: 16777212 3096 16774116
In this case, if the other process disconnects and then re-connects, ncat will keep running and accept the new connection.
4. Connecting to a Port
Instead of listening on a port, we may want to connect to a port to receive the information. In this case, the other process listens on a port and sends the information to the process that connects to it. There are two ways to connect to a port. One involves using nc or ncat, and the other involves using a special file.
4.1. Using nc or ncat
When we want to connect to a port, we have to specify the IP and the port number that we want to connect. Sometimes, instead of the IP, we can use a domain name. Once we have the IP and port, we can connect to it using nc. We have to use the IP and the port as the parameters, in that order. Let’s see how to connect to port 9100 on IP 127.0.0.1 using nc:
$ nc 127.0.0.1 9100
Sun Jan 14 16:18:00 -03 2022
total used free shared buff/cache available
Mem: 16311396 3260132 2883652 35496 10167612 12676312
Swap: 16777212 3096 16774116
Sun Jan 14 16:19:00 -03 2022
total used free shared buff/cache available
Mem: 16311396 3270692 2873076 35492 10167628 12665756
Swap: 16777212 3096 16774116
As we can see, nc is connected to IP 127.0.0.1 port number 9100. Then, it received the information and printed it to the terminal. If we want to use the ncat command, we can use the same parameters:
$ ncat 127.0.0.1 9100
Sun Jan 14 16:27:00 -03 2022
total used free shared buff/cache available
Mem: 16311396 3332328 2812052 34188 10167016 12605424
Swap: 16777212 3096 16774116
We can notice, here, that both nc and ncat behave the same way.
4.2. Using a Special File
Finally, there’s another option when we want to connect to a port. We can use Bash functionality that involves opening a special file on /dev/tcp/. This file won’t exist — however, Bash interprets this file as a TCP connection. We can specify the IP as a folder inside /dev/tcp/ and the port as the file. For instance, we can use /dev/tcp/127.0.0.1/9100 to connect to IP 127.0.0.1 port 9100. As that path is treated as a file, we can use cat on that file. However, we have to use Bash redirections to use this functionality. *Let’s try using cat and redirecting /dev/tcp/127.0.0.1/9100 to cat‘s input*:
$ cat </dev/tcp/127.0.0.1/9100
Sun Jan 14 18:01:00 -03 2022
total used free shared buff/cache available
Mem: 16311396 3563388 2561448 36236 10186560 12372308
Swap: 16777212 3096 16774116
We can use any program that reads from the standard input. For instance, we can use tee instead of cat. *Let’s redirect the special file to tee‘s standard input, and save the information to a file*:
$ tee memory_usage_logs.txt </dev/tcp/127.0.0.1/9100
Sun Jan 14 18:29:00 -03 2022
total used free shared buff/cache available
Mem: 16311396 3654996 2468124 34004 10188276 12282940
Swap: 16777212 3096 16774116
^C
$ cat memory_usage_logs.txt
Sun Jan 14 18:29:00 -03 2022
total used free shared buff/cache available
Mem: 16311396 3654996 2468124 34004 10188276 12282940
Swap: 16777212 3096 16774116
Using this special file is a simple method, and we only need Bash in order to use it. However, this method only works when we need to connect to the port — it’s not available when we need to listen to a port.
5. Conclusion
In this article, we learned how to receive information over the network. First, we saw we can bind to a port and listen to it, using nc or ncat, and print the information to the terminal. Then, we saw we can also receive information by connecting to a port using nc, ncat, or a special file*.*