#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> #include <sys/ioctl.h> #include <string.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <netdb.h> #include <signal.h> #define DEF_PROC_NUM 2 #define PROC_NUM_LIMIT 128 #define UDP_PORT 54321 int server(int s) { struct sockaddr_in remote_address; int r, len; #define BUF_SIZE 256 char buf[BUF_SIZE]; signal(SIGPIPE, SIG_IGN); for (;;) { socklen_t sin_size = sizeof(struct sockaddr_in); remote_address.sin_family = AF_INET; remote_address.sin_port = htons(0); remote_address.sin_addr.s_addr = 0; memset( &(remote_address.sin_zero), 0, 8); memset(buf, 0, BUF_SIZE); r = recvfrom(s, buf, BUF_SIZE, MSG_PEEK, (struct sockaddr*)&remote_address, &sin_size); if ( -1 == r ) { perror("recvfrom()"); } len = 0; while ( (buf[len] != '@') && (len < BUF_SIZE-1)) len++; memset(buf, 0, BUF_SIZE); r = recvfrom(s, buf, len + 1, 0, (struct sockaddr*)&remote_address, &sin_size); if ( -1 == r ) { perror("recvfrom()"); } sleep(3); /* we are working hard, yeaaah ... */ memset(buf, 0, BUF_SIZE); sprintf(buf, "%d\n", len); r = sendto(s, buf, strlen(buf), 0, (struct sockaddr*)&remote_address, sizeof(struct sockaddr_in)); if ( -1 == r ) { perror("sendto()\n"); }; }; } int procnum = DEF_PROC_NUM; int udp_sock; struct sockaddr_in local_address; int main(int argc, char *argv[]) { int r, p, pid; int yes = 1; if (argc > 2) { printf("usage: %s [number of server processes]\n", argv[0]); exit(1); }; if (argc == 1) { printf("number of server process is not specified, defaults to %d\n", procnum); } else { r = sscanf(argv[1], "%d", &procnum); if ( r != 1) { printf("number of server process is bad, defaults to %d\n", procnum); }; if (procnum > PROC_NUM_LIMIT) { procnum = PROC_NUM_LIMIT; printf("number of server process is too large, using max (%d)\n", procnum); } } /* create udp socket */ udp_sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); if ( udp_sock == -1 ) { perror("socket()"); exit(1); }; r = setsockopt(udp_sock, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)); if ( -1 == r ) { perror("setsockopt()"); exit(1); }; local_address.sin_family = AF_INET; local_address.sin_port = htons(UDP_PORT); local_address.sin_addr.s_addr = INADDR_ANY; memset( &(local_address.sin_zero), 0, 8); r = bind(udp_sock, (struct sockaddr*)&local_address, sizeof(struct sockaddr)); if ( -1 == r ) { perror("bind()"); exit(1); } /* prefork */ for (p = 0; p < procnum; p++) { pid = fork(); switch (pid) { case -1: ;;; perror("fork()"); ;;; break; /* child process */ case 0: ;;; server(udp_sock); ;;; break; /* parent */ default: ;;; printf("child process (pid = %d) created\n", pid); ;;; }; }; exit(0); }