IPv4 Daytime Server
Author: Eva M. Castro eva arroba gsyc.es |
The server is composed of a main program and communication library, which is reduced to a simple function.
The main program is devoted to get program parameters and call listen_server function. Each connection restarts the process and local time and date is returned to the client.
The difference between TCP and UDP versions is the listen_server call: accept (which is replaced by receivefrom) and write (which is replaced by sendto)
First of all, network libraries should be included:const char *DAYTIME_PORT="13"; int main(int argc, char *argv[]) { int listenfd, connfd, port; socklen_t addrlen; char timeStr[256]; char *clienthost; struct sockaddr_in clientaddr; time_t now; /* local server socket listening at daytime port=13 */ listenfd = listen_server(NULL,DAYTIME_PORT,AF_INET,SOCK_STREAM); if (listenfd < 0) { fprintf(stderr, "listen_socket error:: could not create listening " "socket\n"); return -1; } for ( ; ;) { addrlen = sizeof(clientaddr); /* accept daytime client connections */ connfd = accept(listenfd, (struct sockaddr *)&clientaddr, &addrlen); if (connfd < 0) continue; clienthost = inet_ntoa(clientaddr.sin_addr); port = ntohs(clientaddr.sin_port); printf("Received request from host=[%s] port=[%d]\n", clienthost, port); /* process daytime request from a client */ memset(timeStr, 0, sizeof(timeStr)); time(&now); sprintf(timeStr, "%s", ctime(&now)); write(connfd, timeStr, strlen(timeStr)); close(connfd); } return 0; }
The core of communications is the listen_server function. It is devoted to setup the server and wait for clients connections. It initializes the server socket and blocks the process waiting for a client connection. The function returns when a client appears.#include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <netdb.h> #include <stdio.h> #include <errno.h> #include <time.h> #include <unistd.h> #include "listen_server.h"
If IP number should be used, it is managed inside listen_server, not outside in the main program.
#include <types.h> #include <socket.h> #include <stdlib.h> #include <stdio.h> #include "listen_server.h" const int LISTEN_QUEUE=128; int listen_server(const char *hostname, const char *service, int family, int socktype) { struct sockaddr_in sin; struct hostent *phe; struct servent *pse; struct protoent *ppe; int sockfd; char *protocol; memset(&sin, 0, sizeof(sin)); sin.sin_family=AF_INET; switch(socktype) { case SOCK_DGRAM: protocol= "udp"; break; case SOCK_STREAM: protocol= "tcp"; break; default: fprintf(stderr, "listen_server:: unknown socket " "type=[%d]\n", socktype); return -1; } if ( pse = getservbyname(service, protocol) ) { sin.sin_port = pse->s_port; } else if ( (sin.sin_port = htons((u_short)atoi(service))) ==0) { fprintf(stderr, "listen_server:: could not get " "service=[%s]\n", service); return -1; } if (!hostname) { sin.sin_addr.s_addr= INADDR_ANY; } else { if (phe = gethostbyname(hostname)) { memcpy(&sin.sin_addr, phe->h_addr, phe->h_length); } else if ( (sin.sin_addr.s_addr = inet_addr(hostname)) == INADDR_NONE) { fprintf(stderr, "listen_server:: could not get " "host=[%s]\n", hostname); return -1; } } if ((ppe = getprotobyname(protocol)) == 0) { fprintf(stderr, "listen_server:: could not get " "protocol=[%s]\n", protocol); return -1; } if ((sockfd = socket(PF_INET, socktype, ppe->p_proto)) < 0) { fprintf(stderr, "listen_server:: could not open socket\n"); return -1; } if (bind(sockfd, (struct sockaddr *)&sin, sizeof(sin)) != 0) { fprintf(stderr, "listen_server:: could not bind socket\n"); close(sockfd); return -1; } listen(sockfd, LISTEN_QUEUE); return sockfd; }
Author: Eva M. Castro eva arroba gsyc.es |