In the current article, we try and analyze what occurs at each stage of the Stream socket connection example.
The Stream Socket example code for IPv4 is provided at this link here. The interested reader can look at the code on his linux shell and try and follow the actual connection establishment here.
The initial code to create a socket on the server or the client is provided below
/* Part 1 – create a socket */
/* create the socket FD */
socket_fd = socket(AF_INET, SOCK_STREAM, 0);
if (socket_fd < 0) {
printf(“The Socket API call failed\n”);
exit(0);
}
If the above call to “socket API” succeeds, then a socket File Descriptor is provided to the application invoking the socket call. The socket is currently not bound to any address. The “Bind API” will bind the socket to an address at the server side. The code for bind is shown below
serveraddr->sin_addr.s_addr = inet_addr(“127.0.0.1”);
serveraddr->sin_port = htons(PORT);
/* Part 3 – bind and start accepting connections */
if(0 != bind(socket_fd, (struct sockaddr *)serveraddr, sizeof(struct sockaddr_in))) {
printf(“unable to bind to the socket\n”);
goto end1;
}
/* accept up-to 5 pending requests
* and make the server socket a passive socket to accept clients
*/
if (listen(socket_fd, 5) == -1) {
printf(“Listen Failed\n”);
goto end1;
}
When Bind API succeeds, the socket File descriptor will be bound to a Port and IP address. The socket is placed in listen state to accept client connections. The output of the “ss shell command” after the successful invocation of listen shows the current state of the bound socket to be in listen state. The socket state is marked in Red. It can be seen that the socket is in listen state and bound to 127.0.0.1:55000 and does not have a peer connection yet
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 128 127.0.0.53%lo:domain 0.0.0.0:*
LISTEN 0 5 127.0.0.1:ipp 0.0.0.0:*
LISTEN 0 5 127.0.0.1:55000 0.0.0.0:*
TIME-WAIT 0 0 192.168.0.6%enp0s3:51034 35.224.99.156:http
LISTEN 0 5 [::1]:ipp [::]:*
After entering into listen state, the server code will await for incoming connections on an accept API call. The code for the same is provided below
/* accept is a blocking call and the call would stop further invocation of * code till a client connection is accepted */
printf(“waiting for connection\n”);
clientfd = accept(socket_fd, (struct sockaddr *)clientaddr, &length);
if (clientfd < 0) {
printf(“Unable to connect to Client FD\n”);
goto end2;
}
clientfd is a socket file descriptor and is the client connection socket. Note that, accept is a blocking call and the server will wait for incoming connections at the instance of accept API invocation.
On the client side, after a socket is created, the client tries to connect to the IPaddress and port combination of the server. Notice that the client does not bind in this example case. The Kernel will provide a port number for the client socket. The code snippet achieving that operation for the client is provided below
sockaddrin->sin_family = AF_INET;
sockaddrin->sin_port = htons(PORT);
sockaddrin->sin_addr.s_addr = inet_addr(“127.0.0.1”);
/* part 3 – connect to the server defined by IP address and port*/
/* connect to the server */
if (0 != connect(socket_fd, (struct sockaddr *)sockaddrin,
(socklen_t)(sizeof(struct sockaddr_in)))) {
printf(“Unable to connect\n”);
/* unable to connect to server */
goto end1;
}
if connect attempt to the server succeeds, then the socket connection is established and the socket can be used to transmit and receive data on the socket. The port number for the client is allocated by the linux kernel.
The connect API on a TCP stream socket invokes a TCP 3-way handshake. The output of the “ss shell command” after connect and the 3-way handshake is also provided below for the reader’s understanding and reference
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 128 127.0.0.53%lo:domain 0.0.0.0:*
LISTEN 0 5 127.0.0.1:ipp 0.0.0.0:*
LISTEN 0 5 127.0.0.1:55000 0.0.0.0:*
ESTAB 50 0 127.0.0.1:57798 127.0.0.1:55000
ESTAB 0 50 127.0.0.1:55000 127.0.0.1:57798
LISTEN 0 5 [ ::1]:ipp [::]:*
The interested reader can run Wireshark on the loopback interface (since the socket is created on the lo address – 127.0.0.1) and capture the three way handshake.
Pingback: A Socket Server/Client Example – TCP Stream Sockets | Hitch Hiker's Guide to Learning