Spread the love

SOCKETS :

A socket is a communication mechanism that allows client/server systems to be developed either locally, on a single machine, or across networks. Linux functions such as printing, connecting to databases, and serving web pages as well as network utilities such as rlogin for remote login, http for hyper text transfer protocol and ftp for file transfer usually use sockets to communicate.
Sockets are created and used differently from pipes because they make a clear distinction between client and server. The socket mechanism can implement multiple clients attached to a single server.

socket

Socket Connections

First, a server application creates a socket, which like a file descriptor is a resource assigned to the server process and that process alone. The server creates it using the system call socket, and it can’t be shared with other processes.

Next, the server process gives the socket a name. For example, a web server typically creates a socket on port 80, an identifier reserved for the purpose. Web browsers know to use port 80 for their HTTP connections and port 443 for HTTPS connections.

  • A socket is named using the system call bind.
  • The system call, listen, creates a queue for incoming connections.
  • The server can accept them using the system call accept.

When the server calls accept, a new socket is created that is distinct from the named socket. This new socket is used solely for communication with this particular client.

The client side of a socket-based system is more straightforward. The client creates an unnamed socket by calling socket.

Socket Attributes

Sockets are characterized by three attributes: domain, type, and protocol.

Socket Domains :Domains specify the network medium that the socket communication will use. The most common socket domain is AF_INET, which refers to Internet networking that’s used on many Linux local area networks and, of course, the Internet itself.

Protocols : Internet protocols provide two communication mechanisms with distinct levels of service: streams and datagrams.

  • Stream Sockets : Stream sockets (in some ways similar to standard input/output streams) provide a connection that is a sequenced and reliable two-way byte stream. Thus, data sent is guaranteed not to be lost, duplicated, or
    reordered without an indication that an error has occurred.
  • Datagram Sockets :   A datagram socket, specified by the type SOCK_DGRAM, doesn’t establish and maintain a connection. There is also a limit on the size of a datagram that can be sent. It’s transmitted as a single network message that may get lost, duplicated, or arrive out of sequence.

Creating a Socket

The socket system call creates a socket and returns a descriptor that can be used for accessing the socket.

Syntax :

#include <sys/types.h>
#include <sys/socket.h>
int socket(int domain, int type, int protocol);

Naming a Socket

To make a socket (as created by a call to socket) available for use by other processes, a server program needs to give the socket a name. The bind system call assigns the address specified in the parameter, address, to the unnamed socket associated with the file descriptor socket. The length of the address structure is passed as address_len.

Syntax :

#include <sys/socket.h>
int bind(int socket, const struct sockaddr *address, size_t address_len);

Creating a Socket Queue

To accept incoming connections on a socket, a server program must create a queue to store pending requests. It does this using the listen system call.

Syntax :

#include <sys/socket.h>
int listen(int socket, int backlog);

A value of 5 for backlog is very common.

Accepting Connections

Once a server program has created and named a socket, it can wait for connections to be made to the socket by using the accept system call.

Syntax :

#include <sys/socket.h>
int accept(int socket, struct sockaddr *address, size_t *address_len);

Requesting Connections

Client programs connect to servers by establishing a connection between an unnamed socket and the server listen socket. They do this by calling connect.

Syntax :

#include <sys/socket.h>
int connect(int socket, const struct sockaddr *address, size_t address_len);

Closing a Socket

You can terminate a socket connection at the server and client by calling close, just as you would for low level file descriptors.

Example of SOCKET Communication in LINUX

Let us take a server-client example to illustrate socket communication between two processes.

  • client.c
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<netdb.h>
#include<unistd.h>
#define DATA "Hello World"

int main(int argc,char *argv[])
{
	int sock,i;
	struct hostent *hp;
	struct sockaddr_in server;
	char buff[1024],data[100],ch;
	while(1)
	{	
	sock=socket(AF_INET,SOCK_STREAM,0);
	if(sock<0)
	{
		perror("\nSocket failed\n");
		exit(1);
	}
	server.sin_family=AF_INET;
	hp=gethostbyname(argv[1]);
	if(hp==0)
	{
		perror("\ngethostbyname failed......\n");
		exit(1);
	}
	memcpy(&server.sin_addr,hp->h_addr,hp->h_length);
	server.sin_port=htons(6000);		//converts unsigned short integer from host byte order to network bbyte order.
	if(connect(sock,(struct sockaddr *)&server,sizeof(server))<0)
	{
		perror("Connect failed\n");	
		exit(1);
	}
	printf("Enter data to send:");
//	scanf("%s",data);
	i=0;
	ch=getchar();
	do
	{
		data[i]=ch;
		ch=getchar();
		i++;
	}while(ch!='\n');
	data[i]='\0';
	if(send(sock,data,sizeof(data),0)<0)
	{
		perror("send failed\n");
		close(sock);
		exit(1);
	}
	printf("\nSent:%s\n",data);
	close(sock);
	}
	return 0;

}

OUTPUT :

error

On compiling client.c, we provide localhost as a command line argument to connect the system with localhost i.e. 127.0.0.1, But the connection was refused because the server is unavaliable.

  • server.c
#include<stdio.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<string.h>
#include<stdlib.h>

int main(int argc,char *agrv[])
{
	/*Variables*/
	int sock;
	struct sockaddr_in server;
	int mysock;
	char buff[1024];
	int rval;
	
	/*Create Socket*/

	sock=socket(AF_INET,SOCK_STREAM,0);
	if(sock<0)
	{
		perror("\nFailed to create socket\n");
		exit(1);
	}
	server.sin_family=AF_INET;
	server.sin_addr.s_addr=INADDR_ANY;
	server.sin_port=htons(6000);
	
	/*Call Bind*/
	
	if(bind(sock,(struct sockaddr *)&server,sizeof(server)))
	{
		perror("\nBind Failed\n");
		exit(1);
	}
	
	/*Listen*/

	listen(sock,5);

	/*Accept*/
	
	do
	{
		printf("\nWaiting....\n");
		mysock=accept(sock,(struct sockaddr *)0,0);
		if(mysock==-1)
		{
			perror("\nAccept failed\n");
			exit(1);
		}
		else
		{
			memset(buff,0,sizeof(buff));
			if((rval=recv(mysock,buff,sizeof(buff),0))<0)
			{
				perror("\nReading stream message error\n");
				exit(1);
			}
			else if(rval==0)
				printf("\nEnding Connection\n");
			else
			{
				printf("MSG:%s\n",buff);
			}
			printf("Got the message(rval=%d)",rval);
			close(mysock);
		}
	}while(1);
	return 0;
}
		

Output :

Now again run client .c  –

client

compile server.c and run simultaneously ,

2_socket

 

Suggested Reading

  1. LINUX CHAT MESSENGER PROJECT USING MESSAGE QUEUE
  2. Signal in Linux
  3. Process in Linux
  4. Inter Process Communication in Linux with Examples