APUE练习16.3

 1 /**

 2 *initserver.c

 3 **/

 4 

 5 #include <stdio.h>

 6 #include <stdlib.h>

 7 #include <sys/socket.h>

 8 #include <netinet/in.h>

 9 #include <syslog.h>

10 #include <errno.h>

11 

12 int

13 initserver(int type, const struct sockaddr *addr, socklen_t alen, int qlen)

14 {

15     int fd;

16     int err = 0;

17     int reuse = 1;

18 

19     if((fd = socket(addr->sa_family, type, 0)) < 0)

20         return -1;

21 

22     if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(int)) < 0) {

23         err = errno;

24         goto errout;

25     }

26 

27     if(bind(fd, addr, alen) < 0) {

28         err = errno;

29         goto errout;

30     }

31     

32     syslog(LOG_DEBUG, "in initserver port: %d\n",((struct sockaddr_in *)addr)->sin_port);

33 

34     if(type == SOCK_STREAM || type == SOCK_SEQPACKET) {

35         if(listen(fd, qlen) < 0)

36         {

37             err= errno;

38             goto errout;

39         }

40     }

41 

42     return (fd);

43     

44 errout:

45     close(fd);

46     errno = err;

47     return -1;

48 }

服务器端:

  1 #include <stdio.h>

  2 #include <stdlib.h>

  3 #include <string.h>

  4 #include <syslog.h>

  5 #include <sys/socket.h>

  6 #include <sys/select.h>

  7 #include <netdb.h>

  8 #include <errno.h>

  9 

 10 #define BUFLEN 128

 11 #define QLEN 10

 12 

 13 #ifndef HOST_NAME_MAX

 14 #define HOST_NAME_MAX 256

 15 #endif

 16 

 17 extern int initserver(int, struct sockaddr *, socklen_t , int);

 18 

 19 void

 20 serve(fd_set *sockset, int maxfd, int index, int fd_arr[])

 21 {

 22     int clfd, listenfd;

 23     int i;

 24     int nready;

 25     FILE *fp;

 26     char buf[BUFLEN];

 27 

 28     for(;;) {

 29         if((nready = select(maxfd+1, sockset, NULL, NULL, NULL)) > 0) {

 30             for(i = 0; i < index; i++) {

 31                 listenfd = fd_arr[i];                

 32                 if(FD_ISSET(listenfd, sockset)) {

 33                     clfd = accept(listenfd, NULL, NULL);

 34                     

 35                     if(clfd < 0) {

 36                         syslog(LOG_ERR, "ruptime: accept error:%s",

 37                         strerror(errno));

 38                         exit(1);

 39                     }

 40                     

 41                     if((fp = popen("/usr/bin/uptime", "r")) == NULL) {

 42                         sprintf(buf, "error:%s\n", strerror(errno));

 43                         send(clfd, buf, strlen(buf), 0);

 44                     } else {

 45                         while(fgets(buf, BUFLEN, fp) != NULL)

 46                         send(clfd, buf, strlen(buf), 0);

 47                         pclose(fp);

 48                     }

 49                     close(clfd);

 50                 }

 51             }

 52         }

 53     }

 54 }

 55 

 56 int

 57 main(int argc, char *argv[])

 58 {

 59     struct addrinfo *ailist, *aip;

 60     struct addrinfo hint;

 61 

 62     int sockfd, err, n;

 63     int fd_arr[FD_SETSIZE];

 64     fd_set sockset;

 65     int maxfd = -1;

 66     int index = 0;

 67     char *host;

 68 

 69     if(argc != 1) {

 70         printf("usage: ruptimed");

 71         exit(1);

 72     }

 73 

 74 #ifdef _SC_HOST_NAME_MAX

 75     n = sysconf(_SC_HOST_NAME_MAX);

 76     if(n < 0)

 77 #endif

 78 

 79     n = HOST_NAME_MAX;

 80     host = malloc(n);

 81     if(host == NULL) {

 82         perror("malloc error");

 83         exit(1);

 84     }

 85 

 86     if(gethostname(host, n) < 0) {

 87         perror("gethostname error");

 88         exit(1);

 89     }

 90     printf("in main pid: %d\n", getpid());

 91 

 92     daemonize("ruptimed");

 93     hint.ai_flags = AI_CANONNAME;

 94     hint.ai_family = 0;

 95     hint.ai_socktype = SOCK_STREAM;

 96     hint.ai_protocol = 0;

 97     hint.ai_addrlen = 0;

 98     hint.ai_canonname = NULL;

 99     hint.ai_next = NULL;

100     

101     syslog(LOG_DEBUG, "ruptimed pid: %d\n", getpid());

102     if((err = getaddrinfo(host, "ruptime", &hint, &ailist)) != 0) {

103         syslog(LOG_ERR, "ruptimed: getaddrinfo error: %s", gai_strerror(err));

104         exit(1);

105     }

106     

107     FD_ZERO(&sockset);

108     memset(fd_arr, 0, sizeof(int));

109 

110     for(aip = ailist; aip != NULL; aip = aip->ai_next) {

111         syslog(LOG_DEBUG, "main port: %d\n", ntohs(((struct sockaddr_in *)aip->ai_addr)->sin_port));

112         if((sockfd = initserver(SOCK_STREAM, aip->ai_addr, aip->ai_addrlen, QLEN)) >= 0) {

113             if(sockfd > maxfd)

114                 maxfd = sockfd;

115             FD_SET(sockfd, &sockset); 

116             //serve(sockfd);

117             //exit(0);

118             fd_arr[index] = sockfd;

119             index++;

120         }

121     }

122     if(maxfd >= 0) {

123         serve(&sockset, maxfd, index, fd_arr);

124     }

125     exit(1);

126 }

注意:借用int数组fd_arr记录用于监听的套接字,在函数serve中,并不能确定较小数值套接字一定比较大数值套接字先准备好,所以

1  for (sockfd = 0; FD_ISSET(sockfd, sockfdsp); ++sockfd)

这样的循环是错误的。我这里用index记录套接字数量,fd_arr记录套接字,然后调用FD_ISSET遍历。

另外,在initserver函数中,调用了setsockopt,取消了TIME_WAIT的限制。

你可能感兴趣的:(UE)