Saturday, May 10, 2008

Unix - Illustration of simple daytime client and server


Unix Network Programming is my another area of interest and i start it with this blogpost illustrating a simple daytime client and server communication. More posts will follow with more specialized areas.


Simple Daytime client


Its is a very basic illustration of a client establishing a TCP connection with a server and the server sends back the current time and date.
Following is the code written for daytime client.


#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>

int main(int argc, char **argv) {
int sockfd,n=0;
char recvline[1000+1];
struct sockaddr_in servaddr;

if(argc!=2) {
printf("Error with arguments!!!");
exit(0);
}
if( (sockfd = socket(AF_INET,SOCK_STREAM,0)) < 0) {
printf("Socket Error!!!");
exit(0);
}
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(13);
if(connect(sockfd,(struct sockaddr *) &servaddr,sizeof(servaddr))<0) {
printf("Connect Error!!!");
exit(0);
}
else {
while( (n=read(sockfd,recvline,1000))>0) {
recvline[n] = 0; /* null terminate */
if(fputs(recvline,stdout) == EOF) {
printf("fputs error!!!");
exit(0);
}
}
}
if(n<0) {
printf("read error!!!");
exit(0);
}
exit(0);
}

Following steps are the descriptions of the functioning of client
1. Create TCP Socket: The socket function creates an Internet stream socket. It returns an int which is used as the socket indicator for future references.
2. Soecify Server's IP address and port: Initialize the socket address structure to zero using bzero and set the port number to 13 (default port of daytime server on any TCP/IP host). Set the IP address as the command line argument. Methods hton(int ) (hton - host to network short) converts the binary port number and inet_pton( ) converts ASCII command line argument (IP address) to a proper format.
3. Establish connection with server: The connect function is used to establish a TCP connection with the server specified by the socket address pointed by the second argument.
4. Read server's reply and display: Since TCP is a byte stream protocol, we cannot expect server's reply as one big read of streams of bytes. Based on the size of data and other circumstances, the number of read may vary and its very very essential to enclose read within a loop and check for EOF.
5.Terminate program


Simple Daytime server


Following is the implementation of simple daytime server which communicates with the client written above.


#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>

int main(int argc,char **argv)
{
int listenfd,connfd;
struct sockaddr_in servaddr;
char buff[1000];
time_t ticks;
listenfd = socket(AF_INET,SOCK_STREAM,0);

bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(13);

bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr));

listen(listenfd,8);
for( ; ; ) {
connfd = accept(listenfd,(struct sockaddr *)NULL,NULL);

ticks = time(NULL);
snprintf(buff,sizeof(buff),"%.24s\r\n",ctime(&ticks));
write(connfd,buff,strlen(buff));
close(connfd);
}
}

Following are the steps pertaining to daytime server's functioning.
1. Create a TCP socket: Similar to client implementation.
2. Convert socket to listening socket: Any TCP server has to prepare its listening descriptor and has to perform socket, bind and listen. This converts a normal socket to a listening socket. Constant 8 is used to specify the max no. of client connections that the kernel will queue for this listening descriptor.
3. Accept client connection and send reply: Once server enters into accept, the server process is put into sleep in the call to accept, waiting for client connection to arrive and accepted. A TCP connection uses 3-way handshake to achieve this successful connection establishment with another node (client/server). Once a connection arrives at the server, accept returns a connection descriptor and using that the current time at the server is written to the write buffer.
4. Terminate connection:Use close(connection desc) to close the connection one by one.


Steps to compile and run the daytime client and server programs



1. Save client program under the name daytimetcpcli.c under any directory. i have saved it in my /root.
2. Save server program under the name daytimetcpsrv.c under any directory. i have saved it in my /root.
Running Server:
3. Compile daytimetcpsrv.c first (because server should be ready before client requests for a response) using the command cc daytimetcpsrv.c.
4. Run the server program using the command ./a.out.
Running Client:
5. Open another terminal.
6. Compile daytimetcpcli.c using the command cc daytimetcpcli.c.
7. Run the client program with IP address as command line argument. Since the server is running in the same machine as the client runs, we can mention the IP address as 127.0.0.1 (localhost). Hence type ./a.out 127.0.0.1 and press return key.
8. Client shows the current time of the server.


Output screenshots



Fig 1 Compiling daytime server


Fig 2 Running daytime server


Fig 3 Compiling and running daytime client

Executed under Fedora ver 6

10 comments:

Anonymous said...

Hello...i copied the server client code as it is ...but its giving me errors ..."connect errror"...its not able to connect to local host..

Anonymous said...

Hi
Very nice and intrestingss story.

Anonymous said...

This code leaves error dude.u have not used inet_pton in client program

sowjanya said...

hi.... i compiled but i am getting the error as"Error with arguments!!!"

Anonymous said...

hi i compiled the program and i am getting the error as "Error with arguments!!!"pls sugst.

Anonymous said...

Hi,

I begin on internet with a directory

Anonymous said...

That's because the client is missing a line. Add:

servaddr.sin_addr.s_addr = inet_addr(argv[1]);

right after the servaddr.sin_port line.

monish001 said...

Output is Connect Error, when run in Ubuntu 10.04. Please reply.

monish001 said...

In Ubuntu 10.04, the program gives "Connect Error!"

Server Program gives following warnings:
daytimetcpsrv.c: In function ‘main’:

daytimetcpsrv.c:16: warning: incompatible implicit declaration of built-in function ‘bzero’

daytimetcpsrv.c:28: warning: format ‘%.24s’ expects type ‘char *’, but argument 4 has type ‘int’

daytimetcpsrv.c:28: warning: format ‘%.24s’ expects type ‘char *’, but argument 4 has type ‘int’

daytimetcpsrv.c:29: warning: incompatible implicit declaration of built-in function ‘strlen’


Client Program gives following warnings:

daytimetcpcli.c: In function ‘main’:

daytimetcpcli.c:14: warning: incompatible implicit declaration of built-in function ‘exit’

daytimetcpcli.c:18: warning: incompatible implicit declaration of built-in function ‘exit’

daytimetcpcli.c:20: warning: incompatible implicit declaration of built-in function ‘bzero’

daytimetcpcli.c:25: warning: incompatible implicit declaration of built-in function ‘exit’

daytimetcpcli.c:32: warning: incompatible implicit declaration of built-in function ‘exit’

daytimetcpcli.c:38: warning: incompatible implicit declaration of built-in function ‘exit’

daytimetcpcli.c:40: warning: incompatible implicit declaration of built-in function ‘exit’

-Monish

Anonymous said...

Adding the line
servaddr.sin_addr.s_addr = inet_addr(argv[1]);
fixed it for me (see above).