/* udpservb.c * Server using datagram service with sockets. It is called with one * parameter, the name of the port it will use. In a loop, it accepts * a message from a client, and it creates a thread to take care of the * message. The server has a timeout when waiting. * A thread prints out a message it receives, sleeps a bit, then * answers the client with a message that consists of a prefix * contained in the message received and with the current time. */ #include #include #include #include #include #include #include #include #define MAXBUF 2 * 1024 #define MAXSERVWAIT 3 #define PREFIXSIZE 23 pthread_t *threadp; /* Pointer to thread that will handle a request */ /* [There may be multiple active threads. Only */ /* last is kept track of.*/ struct request { /* Descriptor of a request from client */ char b[MAXBUF]; /* The message from client */ struct sockaddr_in client_addr; /* the address of the client */ }; void handle(struct request *b); /* Function executed by thread */ int sock; /* file descriptor for UDP datagram socket */ main(argc, argv) int argc; char *argv[]; { int create_request = 1; /* it is 1 when we need to create a request */ struct request *requestp; /* Pointer to a request */ int length; /* length of address */ fd_set read_template; /* used by select statement */ struct timeval pwait; int nb; struct sockaddr_in name; /* the socket used for request */ if (argc < 2) { printf("\nUSE: udpservb serverport\n"); exit(1);} /* * create a socket */ if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { perror("Server: socket"); exit(1);} /* * bind socket */ bzero((char *)&name, sizeof(name)); name.sin_family = AF_INET; name.sin_addr.s_addr = INADDR_ANY; name.sin_port = htons(atoi(argv[1])); if(bind (sock, (struct sockaddr *)&name, sizeof(name)) < 0) { perror("Server: bind"); exit(1); } while(1) { if (create_request) { /* * Allocate request structure */ if ((requestp = (struct request *)malloc(sizeof(struct request))) == 0) { perror("Malloc request"); exit(1);} } /* * Wait for request */ pwait.tv_sec = MAXSERVWAIT; pwait.tv_usec = 0; FD_ZERO(&read_template); FD_SET(sock, &read_template); if ((nb = select(FD_SETSIZE, &read_template, NULL, NULL, &pwait)) <= 0) { printf("Server timed out\n"); create_request = 0; /* No need to create socket in next iteration */ } else if (FD_ISSET(sock, &read_template)) { create_request = 1; length = sizeof(struct sockaddr_in); if(recvfrom(sock, requestp->b, MAXBUF, 0, &requestp->client_addr, &length) < 0) perror("Couldn't read datagram"); /*create thread */ if ((threadp = (pthread_t *)malloc(sizeof(pthread_t))) == 0) { perror("Malloc pthread_t"); exit(1);} if (pthread_create(threadp, pthread_attr_default, (void *) handle, requestp) != 0) { perror("pthread_create"); exit(1);} printf("thread created\n"); /* Code to reclaim the space allocated for thread objects. */ if (pthread_detach(threadp) == 0) { printf("pthread detached\n"); } else { perror("pthread_detach error"); exit(1);} } else { printf ("How did I get here?\n"); exit(1);} } } /* * The code executed by a thread. */ void handle (struct request * b) { struct timespec interval; /* Sleeping time */ long tm; /* Time*/ printf("Thread: From Client %s\n", b->b); interval.tv_sec = 2; interval.tv_nsec = 0; pthread_delay_np(&interval); time(&tm); strcpy(b->b+PREFIXSIZE, ctime(&tm)); printf("Thread: To Client %s\n", b->b); if(sendto(sock, b->b, MAXBUF, 0, &b->client_addr, sizeof(struct sockaddr_in)) < 0) { perror("Thread: Couldn't send datagram");} free(b); }