Learning more about network sockets
While reading through some of the neo4j code a few weeks ago I realised that I didn’t have a very good understanding about the mechanics behind network ports/sockets so I thought I’d try to learn more.
In particular I’d not considered what binding a socket to different network interfaces meant so I decided to setup a few examples using netcat to help me understand better.
To start with let’s list the network interfaces that I have on my machine using ifconfig:
$ ifconfig -u
lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> mtu 16384
options=3<RXCSUM,TXCSUM>
inet6 fe80::1%lo0 prefixlen 64 scopeid 0x1
inet 127.0.0.1 netmask 0xff000000
inet6 ::1 prefixlen 128
en0: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500
ether xxxxxxxxxxxx
inet6 fe80::9afe:94ff:fe4f:ee50%en0 prefixlen 64 scopeid 0x4
inet 192.168.1.89 netmask 0xffffff00 broadcast 192.168.1.255
media: autoselect
status: active
p2p0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 2304
ether xxxxxxxxxxxx
media: autoselect
status: inactive
'p2p0' isn’t active so we’ll only be able to use the other two to make a socket connection on the machine.
We’ll use netcat to setup a server socket on port 4444 listening on the loopback interface:
$ nc -l -k 127.0.0.1 4444
We can use lsof to see how this has been setup:
$ lsof -Pni :4444
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
java 34178 markhneedham 35u IPv6 0x114b98295506482d 0t0 TCP 127.0.0.1:4444 (LISTEN)
Let’s try and connect to that port using netcat:
$ nc -v 127.0.0.1 4444
Connection to 127.0.0.1 4444 port [tcp/krb524] succeeded!
That works as we’d expect but if we try to connect using the IP of the 'en0' interface we’ll get an error:
$ nc -v 192.168.1.89 4444
nc: connect to 192.168.1.89 port 4444 (tcp) failed: Connection refused
However, if we setup netcat to listen on the wildcard interface (0.0.0.0) then we would be able to connect to 4444 regardless of the interface:
$ nc -l -k 0.0.0.0 4444
$ nc -v 192.168.1.89 4444
Connection to 192.168.1.89 4444 port [tcp/krb524] succeeded!
$ nc -v 127.0.0.1 4444
Connection to 127.0.0.1 4444 port [tcp/krb524] succeeded!
If we check lsof it will confirm that we are listening on 4444 on all interfaces:</p ~bash $ lsof -Pni :4444 COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME nc 37725 markhneedham 3u IPv4 0x114b98294ba8dfd5 0t0 TCP *:4444 (LISTEN) ~
One thing I hadn’t realised is that you can set up two different processes listening on the same port but on different interfaces. e.g. ~bash $ nc -l -k 127.0.0.1 4444 $ nc -l -k 0.0.0.0 4444 ~
We can see from lsof how this has been setup: ~bash $ lsof -Pni :4444 COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME nc 38306 markhneedham 3u IPv4 0x114b98294ba8dfd5 0t0 TCP *:4444 (LISTEN) nc 38331 markhneedham 3u IPv4 0x114b98294cc53fd5 0t0 TCP 127.0.0.1:4444 (LISTEN) ~
If we make a socket connection to 127.0.0.1 it goes to our first netcat and if we use 192.168.1.89 the second one is used.
Finally, if we try to bind a server socket on an interface that we don’t own netcat will fail in a fairly predictable way: ~bash $ nc -l -k 192.168.1.90 4444 nc: Can’t assign requested address ~
About the author
I'm currently working on short form content at ClickHouse. I publish short 5 minute videos showing how to solve data problems on YouTube @LearnDataWithMark. I previously worked on graph analytics at Neo4j, where I also co-authored the O'Reilly Graph Algorithms Book with Amy Hodler.