1. Overview
In this tutorial, we’ll discuss the basics of sockets and how to bind any available port to a socket.
2. Introduction to Sockets
Sockets in the computer networks are the endpoints through which two nodes connect and communicate with each other. Additionally, it creates two-way FIFO communication. Moreover, we need to create a socket connection at both ends of the communication. Additionally, a socket address generally contains an IP address and a port number.
Generally, the client-server applications use sockets. In client-server applications, a server is initially responsible for creating a server socket connection. Hence, it connects to a network port address. On the other hand, a client also creates a socket connection and tries to connect with the specific socket server. Therefore, the data transfer between the client and server begins as soon as the connection establishes.
Sockets can be classified into two categories: datagram and stream socket. Datagram sockets are connection-less UDP sockets. Hence, we don’t need to establish any connection in order to transfer data. An example of a datagram socket is the mailbox. Contrary to the datagram sockets, steam-based sockets are connection-oriented stream TCP sockets. Therefore, we need to establish a connection before transferring the data. Additionally, It works the same as a phone.
Therefore, a server node creates a TCP or UDP socket and listens to a certain IP address in a particular port. Next, the server waits for a client to connect. Additionally, a client can connect to the server using the provided remote IP address, port number, and TCP/UDP protocol information. Generally, sockets are supported by all major operating systems. Additionally, sockets provide file descriptors similar to the file system for the computer networks.
3. Basics of Socket Programming
Socket programming is a way to create and connect sockets to send data in a network. Let’s discuss some basics of socket functions and their use in networking.
The function socket() creates a new socket descriptor. The bind() function attaches a socket to a local address or port. We can use listen() to indicate the server socket is ready to receive a connection from the client socket. Now in order to know the connection status, we use accept(), which provides the confirmation.
As soon as we establish a connection between a client and a server socket, we’re ready to start the transfer of data. At first, we use send() to send data to a remote machine. Similarly, the function receive() is used to receive data from a remote machine. Finally, when the data transfer is completed, we use close() to terminate the connection.
Using the command connect(), we try to connect to a server socket using a remote IP address and port. Commonly, it’s used in TCP. However, In UDP, we use sendto() without establishing any connection. Hence, we skip the connect() command in UDP. Let’s take a look at the summary of commands we discussed:
Functions
Description
socket
Creates a new socket descriptor
bind
Attaches a socket to a local address or port
listen
Waits for a client connection
accept
Accepts client connection
send
Sends data to a remote machine
receive
Receives data from a remote machine
close
Closes the connection
connect
Connects to a server socket using remote an IP address and a port in TCP
sendto
Starts the data transfer in UDP
Let’s now look at the stream-based socket connection using the socket functions in TCP:
In the case of datagram-based socket connection using UDP protocol, we don’t need to use connect():
4. Bind Command
The bind command attaches a socket to a local port and reserves the port. Additionally, the bind() function takes the socket descriptor s_d as input and returns status as output:
algorithm BindSocket(s_d):
// INPUT
// s_d = a socket descriptor
// OUTPUT
// true if the socket is successfully bound, otherwise false
server_address <- "127.0.0.1"
port_number <- 8283
length <- sizeof(server_address)
status <- bind(s_d, server_address, port_number, length)
if status = true:
log(status)
else:
log(status)
return status
The input socket descriptor s_d contains socket stream and information of the protocol used for establishing socket connection. Therefore, the bind command is called after calling socket() to attach a local port with the socket descriptor.
The command is used on the server-side so that a client can connect to a particular port assigned during bind. Hence, the server process makes its claim to a specific port through which it can listen to the request of a client. Moreover, the bind command works locally in the same machine. Bind provides an address to receive packets in a server.
Here, we bind the server socket to the mentioned IP address at port 8323. Additionally, the bind call is similar both in the case of TCP and UDP protocols.
5. Different Ways to Bind a Port
In the previous example, we bind TCP or UDP sockets to a particular hard-coded port 8323. However, there’s a possibility that the port is already in use. Hence, it’s not always good to bind to a hard-coded port. Therefore, we can delegate this task to an operating system that can assign a random available port for binding.
Additionally, we can bind any available port by calling bind() with port number 0. Hence, if we don’t specify a fixed port number, the operating system provides one from the available ports:
algorithm BindSocketMethod1(s_d):
// INPUT
// s_d = a socket descriptor
// OUTPUT
// true if the socket is successfully bound, otherwise false
server_address <- "127.0.0.1"
port_number <- 0 // Automatically assigns an available port
length <- sizeof(server_address)
status <- bind(s_d, server_address, port_number, length)
if status = true:
log(status)
else:
log(status)
return status
Additionally, we can generate a random port number from an available set of ports. Hence, if we don’t want to utilize a particular port, we use a randomly assigned port number for communication:
algorithm BindSocketMethod2(s_d):
// INPUT
// s_d = a socket descriptor
// OUTPUT
// true if the socket is successfully bound, otherwise false
server_address <- "127.0.0.1"
ports <- a list of all the available ports
port <- random(port) // Chooses a random port from the available ports
length <- sizeof(server_address)
status <- bind(s_d, server_address, port_number, length)
if status = true:
log(status)
else:
log(status)
return status
6. Conclusion
In this tutorial, we discussed the basics of socket and socket programming. Specifically, we explored different ways of binding a socket to different ports.