How Linux Uses Sockets?


Introduction

Linux is an open-source operating system that has gained immense popularity for its stability and security. It is widely used in various fields such as web servers, embedded systems, and supercomputers.

One of the key aspects of Linux is its efficient usage of sockets for interprocess communication. Sockets provide a flexible way to establish communication channels between different processes running on the same or different machines connected over a network.

What are Sockets?

Sockets are a fundamental concept in Linux networking, allowing communication between processes on different computers over a network. In simple terms, a socket is an endpoint of a two-way communication link that is established between two processes.

A socket consists of an IP address and port number combination. The IP address identifies the remote computer while the port number specifies which program or service on that computer to connect to.

Definition of sockets

In technical terms, a socket is defined as "an endpoint for sending or receiving data across a network". It's essentially an abstraction layer that allows programs to interact with the networking protocols at a high level without worrying about low-level details.

Types of Sockets Used in Linux: Stream, Datagram, Raw, and Sequenced Packet

There are four main types of sockets used in Linux: Stream, Datagram, Raw, and Sequenced Packet. - Stream Sockets (SOCK_STREAM) provide reliable byte-stream communication over TCP/IP protocol and ensure packets arrive in order.

  • Datagram Sockets (SOCK_DGRAM) provide unreliable packet-based communication over UDP protocol.

  • Raw Sockets (SOCK_RAW) provide access to the underlying transport layer protocols such as ICMP and IGMP.

  • Sequenced Packet Sockets (SOCK_SEQPACKET) provide reliable packet delivery with sequencing support but use SCTP (Stream Control Transmission Protocol).

Each type has its strengths and weaknesses depending on the specific use case. Understanding these different types is crucial for efficient network programming using sockets on Linux.

How Sockets Work in Linux

Overview of the Socket Creation Process

Sockets are a fundamental component of network programming, and they allow for communication between Linux processes. In Linux, the creation of a socket is initiated through a function call to the socket() system call.

This function takes three arguments: the address family, socket type, and protocol. The address family specifies whether the socket will be used for communication over an internet protocol (IP) network or on another type of local communications channel.

Explanation of Socket File Descriptors and How They Are Used in Communication

In order for data to be transmitted between two sockets in Linux, each one must have its own unique file descriptor associated with it. These file descriptors are created when sockets are initialized using system calls such as bind(), listen(), accept(), connect(), send() and recv(). When two sockets are communicating with one another through this file descriptor mechanism, they use a standard set of functions known as "socket API" to transmit data back and forth.

Socket Communication Protocols in Linux

TCP/IP Protocol for Reliable Communication Over Networks

The Transmission Control Protocol/Internet Protocol (TCP/IP) is the most commonly used protocol for reliable communication over networks. This protocol ensures that data sent from one device to another arrives at its destination in the correct order and without errors.

TCP/IP uses a three-way handshake to initiate a connection between two devices, followed by data transmission using a sliding window algorithm. This protocol also includes error detection and correction mechanisms to ensure that data integrity is maintained.

UDP Protocol for Fast but Unreliable Communication Over Networks

User Datagram Protocol (UDP) is another popular protocol used in Linux for fast but unreliable communication over networks. Unlike TCP/IP, UDP does not include any error detection or correction mechanisms.

Therefore, there is no guarantee that the data received at the destination will be identical to the data sent from the source. However, because it does not have mechanisms like TCP's sliding window algorithm or three-way handshake, UDP can transmit smaller packets of data faster with less overhead than TCP/IP.

Socket Programming in Linux

Overview of Socket Programming using C Language and System Calls

Socket programming using the C language and system calls is widely used in the Linux development environment. Sockets are created to provide communication between two machines over a network. The socket interface allows programs to communicate with each other through streams or datagrams.

Commonly used system calls include −

  • bind(): assigns a name to a socket

  • listen(): tells a socket to listen for incoming connections

  • accept(): accepts an incoming connection request on a listening socket and creates a new connected socket for communicating with the client process

  • connect(): initiates a connection request on an unconnected socket directed at another endpoint.

  • send():sends data from one endpoint to another, after establishing connection.

  • recv(): takes messages from the queue of incoming messages and places them into buffers provided by user space.

Coding Examples of Socket Programming Concepts

To illustrate how sockets work in Linux, let's look at some code snippets which demonstrate basic operations such as creating and closing sockets, binding them to specific addresses/ports, establishing connections, sending and receiving data −

#include#include
#includeint main() { 
   int sockfd; sockfd=socket(AF_INET,SOCK_STREAM,0); 
   if(sockfd==-1) { 
      printf("Failed to create TCP Socket"); 
      return -1; 
   } else { 
      printf("TCP Socket Created Successfully
"); } close(sockfd); return 0; }

In the above code, we are creating a TCP socket using socket() system call.

It returns a socket descriptor that will be used in other operations. If the value of the descriptor is negative, it means an error occurred while creating a socket.

c #include
#include#include
int main() { 
   int sockfd; 
   struct sockaddr_in server; sockfd=socket(AF_INET,SOCK_STREAM,0); 
   if(sockfd==-1) { 
      printf("Failed to create TCP Socket"); 
      return -1; 
   } else { 
      printf("TCP Socket Created Successfully
"); } bzero(&server,sizeof(server)); server.sin_family=AF_INET; server.sin_port=htons(8000); server.sin_addr.s_addr = INADDR_ANY; if(bind(sockfd,(struct sockaddr*)&server,sizeof(server)) == -1) { perror("Bind Failed:"); return -1; } else { printf("Bind Successfull
"); } close(sockfd); return 0; }

In this example, we are binding our previously created TCP socket to a specific address and port number. The bind() system call takes as input the created socket file descriptor and a pointer to a structure of type sockaddr_in which contains information about the address family (IPv4), IP address (INADDR_ANY) and port number (8000) for the local endpoint.

c #include
#include#include
int main() { 
   int sockfd,newsockfd,portno,n,len; 
   char buffer[256]; struct sockaddr_in serv_addr,client_addr; 
   sockfd=socket(AF_INET,SOCK_STREAM,0); if(sockfd==-1) { 
      printf("Failed to create TCP Socket
"); return -1; } bzero(&serv_addr,sizeof(serv_addr)); portno=8000; serv_addr.sin_family=AF_INET; serv_addr.sin_port=htons(portno); serv_addr.sin_addr.s_addr = INADDR_ANY; if(bind(sockfd,(struct sockaddr*)&serv_addr,sizeof(serv_addr))==-1) { perror("Bind Failed: "); return -1; } listen(sockfd,5); len=sizeof(client_addr); newsockfd=accept(sockfd,(struct sockaddr*)&client_addr,&len); if(newsockfd==-1) { printf("Error in Accepting Client Connection
"); return -1; } else { printf("Client Connected Successfully
"); bzero(buffer,256); n=read(newsockfd,buffer,255); if(n<0) perror("ERROR reading from socket"); printf("%s",buffer); n=write(newsockfd,"Server:
",40); if(n<0) perror("ERROR writing to socket"); close(newsockfd); } close(sockfd); return 0; }

In this code snippet, we are accepting incoming connections on a previously bound socket.

After accepting a connection using accept() function call, we can read data from the client using read() and send data to the client using write() system call. These examples show how sockets can be programmed in Linux using system calls and C language.

Conclusion

Throughout this article, we have explored the important topic of how Linux uses sockets for network programming. We began by defining what sockets are and exploring the different types of sockets used in Linux. We then looked at how sockets work in Linux and the various communication protocols available.

Next, we delved into socket programming using C language and system calls such as bind(), listen(), accept(), connect(), send() and recv(). We covered advanced topics such as multithreaded server programming, non-blocking I/O, and IPv6 support with sockets.

Updated on: 23-Aug-2023

256 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements