Socket Programming using TCP/IP

Socket programs are used to communicate between various processes usually running on different systems. It is mostly used to create a client-server environment. This post  provides the various functions used to create the server and client program and an example program. In the example, the client program sends a file name to the server and the server sends the contents of the file back to the client.

Functions used in server program:

  • socket() –    This call creates an unnamed socket and returns a file descriptor to the calling process.
    usage :   int socket(int domain, int type, int protocol)
    Eg:  sockfd=socket(AF_INET,SOCK_STREAM,0);
    here AF_INET means the the communication is over the internet domain.SOCL_STREAM indicates its a stream type of communication and 0 indicates the protocol used is TCP/IP.
  • bzero()–    this call is used set all the values of the buffer to zero.
    usage: bzero(pointer_to_buffer,size_of_buffer)
    eg:  bzero((char *)&serv_addr,sizeof(serv_addr));
    here serv_addr is of the struct type sockaddr_in which has members used to describe the complete address of a system.
  • serv_addr.sin_family=AF_INET;
    As stated earlier the serv_addr has severaal members and the first of it is sin_family and it contains the code for the address family  and is always AF_INET, indicating the internet domain.
  • serv_addr.sin_addr.s_addr=INADDR_ANY;
    here sin_addr has one member s_addr which is used to hold the IP address of the machine its running in, and this IP ddress is got from the INADDR_ANY constant.
  • serv_addr.sin_port=htons(portno);
    here we hav to store port number into he sin_port member and this takes on the network bute order. So, htons() converts the host byte order representation of the port number to network byte order representation.
  • bind() – It is a system call that binds a socket to an address. Here, the address would be the IP address of the current machine and the port number.
    usage : bind(socket_fd, pointer_of_address_its_bound_to, size_of_address);
    Eg:  bind(sockfd, (struct sockaddr *)&serv_addr,sizeof(Serv_addr)_);
    On failure, it returns a value less than zero.
  • listen() –  This call allows a process to listen on socket for communication.
    usage: listen(socket_fd, no_of_waiting_connections);
    so it takes in a socket file descriptor and  the no. of connections waiting while the process is handling a particular connection. so they wait in a blocking queue.
    Eg : listen(sock_fd,5);
    so 5 connections can wait at the max.
  • accept() –  is a system call that causes the process to block until the client connects to the server.
    it returns a new descriptor and all communication should be carried out using the new file descriptor.
    usage: int accept(sockfd,pointer_to_address_of client, addr_storing_size_of_client_address);
    Eg:  newsockfd= accept(sockfd, (struct sockaddr *)&cli_addr,&clilen);
    here cli_len=sizeof(cli_addr); so the newsockfd has the new socket address which will be used for communication.
    So, this command blocks  until the read() of data is complete that is till the client has finished its write().
  • bzero(buffer,4096);
    n=read(newsockfd,buffer,4096);
    this initializes the buffer to zero and then reads the content from the socket (using the newsockfd) into the buffer. Her since the client sends the file name first, the buffer now contains the filename whose contents has to be sent back. The read(), will also block the process till there is something remaining to read from the socket.
  • fd=open(buffer,O_RDONLY) opens the file requested by the client in the read only mode.
  • read(fd,buffer,4096);
    this reads the contents of the file into the buffer. In socket programming, all communications happens using the buffer both at client and server side. With the completion of this read , the contents of the file is residing in the buffer and is ready to be sent to the client.
  • write(newsockfd,buffer,4096);
    this is the final command ehich writes the contents of the buffer( which has the file content) into the socket using the newsockfd which finally delivers it to the client process.

Functions used in client program:

  • connect() –  is a function used by the client to establish a connetion to the server. It takes 3 arguements:
    usage: connect(sockfd, host_to_which_itconnects, sizeof_addr);
    Eg: connect(sockfd,(struct sockaddr*)&serv_addr,sizeof(Serv_addr))<0);
  • The client too like the server uses the write() to send the file name to server and uses read() to read the content of the file into the buffer. It finally uses write(1,buffer,4096) to print the content on file onto standard output.

The full source code and usage for the client and server can be found here.

Advertisements

Validating user Input in C++

Inputs have to be validated before allowing any kind of processing or operations to be performed on it. This is extremely important because, an unhandled wrong input might have the complete ability to crash a system.  C++ has some good  validation techniques that can be used to validate most kind of inputs. This post discusses some of the techniques and its shortcomings and what could be done to improve the quality of validation.

Now, consider a program has to accept only integer inputs and reject all the others. So, the developer would have declared to store the integer value in say “int a;”. So “a” will store the input value.

When the user input is accepted using the “cin>>a” statement, we can use the inbuilt methods surrounding the “cin”  statement to test its status.

Here is a sample program: –

#include
#include using namespace std;

int main()
{
int a;

 cout<<“Enter an integer number\n”; cin>>a;
while(1)
{
if(cin.fail())
{
cin.clear();
cin.ignore(numeric_limits::max(),’\n’);
cout<<“You have entered wrong input”<<endl; cin>>a;
}
if(!cin.fail())
break;
}

cout<<“the number is: “<<a<<endl;
return 0;
}

From the above example, the various functions are used to validate the input like the cin.fail(), cin.ignore(), etc. The various functions of these methods are :

function

Description

cin.fail() This function returns true when an input failure occurs. In this case it would be an input that is not an integer. If the cin fails then the input buffer is kept in an error state.
cin.clear() This is used to clear the error state of the buffer so that further processing of input can take place. This ensures that the input does not lead to an infinite loop of error message display.
cin.ignore() This function is used to ignore the rest of the line after the first instance of error that has occurred and it skips to or moves to the next line.
cin.eof() This function can be used to check end of file errors. This returns 1  if the program tried reading something but , it was from the end of the file.

NewYearsPromoBusiness-10usd728x90

Here is a screenshot of the various wrong inputs given, and them being handled by the program till a correct  input is provided.

 imput valid

Though this technique seems to work fine it hides a dangerous fault that can occur. This can be considered as a dis advantage of using c++. This technique does not catch certain types of input.
The following screenshots show 2 inputs that is accepted and the numerical part is printed.

invalid1

invalid2

 So, how can this erroneous inputs be handled?
The technique we can apply is to accept the input as a string. The analyze the string to be of the illegal types shown above using regular expressions. If the input is valid then convert it into an integer and use it in the program else display an error message.
Though its possible, its very difficult to be achieved in c++. This is mainly because,  c++ doesn’t support regular expressions by default, we have to make use of the regex library which is quite complex to use.
So to conclude, though C++ provides some handy tools to validate inputs, it does not help us to cover all possible situations in a straight forward way, which would lead us to use other workarounds to get our job done. But the validation of input can be handled in an efficient way with languages like java and c#.

Update 1:  29th Sept 2015

Blog Reader @Nick has provided a solution that is free from reg-ex, and i encourage you to try this out as well and let me know how it works in the comments:

A solution to the problem regex expression free

#include
#include
#include

int main()
{
std::string line;
int num;
//split onto multiple lines for readability
while((std::cout <> num) && !(is >> line)) //re-using `line` to test for extra stuff after the number
{
break; //done, we got what we wanted
}
std::cerr << “Invalid input, try again.” << std::endl;
}
}