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的限制。

转载于:https://www.cnblogs.com/leealways87/archive/2012/10/05/2712233.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值