TCP socket is a fundamental concept in the operation of TCP/IP application world. We will deep dive into the details of how the TCP socket works.
A network socket is defined by the IP address of the machine, the port on which it uses. For example, if we have a website running on IP address 126.96.36.199, the socket corresponding to the HTTP server for that site would be 188.8.131.52:80.
Sockets are classified into stream sockets, socket.SOCK_STREAM, or datagram sockets, socket.SOCK_DGRAM, depending on the underlying protocol we use.
SOCK_STREAM: It is associated with the TCP protocol and provides security in the transmission of data and security in the data reception. In connection-oriented communication, there must be a channel established before we transfer data.
SOCK_DGRAM: It is associated with the UDP protocol and indicates that packets will travel in the datagram type, which has an asynchronous communication style. For UDP sockets, we can send out data without a connection. So this is called connection-less.
Introduction of TCP Sockets
TCP sockets provide an open bi-directional connection between two endpoints. Each connection is uniquely identified using the combination of the client socket and server socket, which in turn contains four elements: the client IP address and port, and the server IP address and port. We call this a TCP socket pair.
For example, we are sending an HTTP request from our client at 184.108.40.206 to the website at 220.127.116.11. The server for that website will use well-known port number 80, so its socket is 18.104.22.168:80, as we saw before. we have been ephemeral port number 3022 for the web browser, so the client socket is 22.214.171.124:3022. The overall connection between these devices can be described using this socket pair: (126.96.36.199:80, 188.8.131.52:3022).
Advantage of TCP Sockets
Is reliable: packets dropped in the network are detected and retransmitted by the sender.
Has in-order data delivery: data is read by our application in the order it was written by the sender.
Example of TCP Sockets
With this Python example, we can better understand how TCP socket works. Let's create a TCP client socket. This is to connect to the remote port 80 on google.com.
# python -c 'import socket;client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM);client_socket.connect(("google.com", 80))'
Then we can use netstat command to check the connection in Linux. All the data will be transferred over this connection. So this TCP socket pair is (10.254.222.37:58596, 184.108.40.206:80)
# netstat -anpl|grep :80 tcp 0 0 10.254.222.37:58596 220.127.116.11:80 TIME_WAIT -
Sending Data with TCP Sockets
For TCP socket, we must create a connection first before sending data to the other side. The following Python command can be used to demonstrate this. It will connect to port 22 on remote host 10.254.222.37 and send some data over this connection and print out the data we receive.
# python -c "import socket ; s = socket.socket(socket.AF_INET, socket.SOCK_STREAM); s.connect(('10.254.222.37', 22)); s.sendall(b'Hello, world');data = s.recv(1024);print data" SSH-2.0-OpenSSH_7.4
If we try to send data to port 23 on the same host, we get some failure messages because the connection is refused.
# python -c "import socket ; s = socket.socket(socket.AF_INET, socket.SOCK_STREAM); s.connect(('10.254.222.37', 23)); s.sendall(b'Hello, world');data = s.recv(1024);print data"
Traceback (most recent call last): File "<string>", line 1, in <module> File "/usr/lib64/python2.7/socket.py", line 224, in meth return getattr(self._sock,name)(*args) socket.error: [Errno 111] Connection refused
Difference between TCP Socket and UDP Socket
Unlike TCP, UDP is a connectionless protocol, so it obviously doesn't use connections. The pair of sockets on the sending and receiving devices can still be used to identify the two processes that are exchanging data, but because there are no connections, the socket pair doesn't have the significance that it does in TCP.
With the following example, we can send some data to remote port 23 with UDP protocol.
We can see that the packet is sent out successfully. UDP doesn't care if the packet is received by the other endpoint or not.
# python -c "import socket ; s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM); s.sendto('hello I am client',('10.254.222.37', 23)); "