zoukankan      html  css  js  c++  java
  • APUE16章的运行示例16-14

    参考文章:http://blog.csdn.net/andyxie407/article/details/1672325

    今天在运行在APUE第16章的16-14(客户端)和16-15(服务端)遇到了不少问题,搞了半天,运行方法多谢andyxie407的文章给了很好地参考(本来就一样,不叫参考),后面还是运行不出结果,结果找到了两个程序抄错了的地方(原谅我,有时候,看一眼大概实现就把代码敲上去了),写都写到这了,还是把我的痛苦运行结果展示一番,代码如下:

    [cpp] view plaincopy在CODE上查看代码片派生到我的代码片
     
    1. //16-14.c 即客户端  
    2. #include "apue.h"  
    3. #include <netdb.h>  
    4. #include <errno.h>  
    5. #include <sys/socket.h>  
    6.   
    7. #define MAXADDRLEN 256  
    8. #define BUFLEN 128  
    9.   
    10. #define MAXSLLEP 128  
    11. int connect_retry(int sockfd, struct sockaddr *addr, socklen_t alen)  
    12. {  
    13.     int nsec;  
    14.   
    15.     for ( nsec = 1; nsec < MAXSLLEP; nsec <<= 1) {//nsec <<= 1 equal to nsec = nsec << 1 equal to nsec /= 2;  
    16.         if (connect(sockfd, addr, alen) == 0)  
    17.             return 0;  
    18.         if (nsec <= MAXSLLEP/2)  
    19.             sleep(nsec);  
    20.     }  
    21.     return -1;  
    22. }  
    23.   
    24. void print_uptime(int sockfd)  
    25. {  
    26.     char    buf[BUFLEN];  
    27.     int     n;  
    28.   
    29.     while ((n = recv(sockfd, buf, BUFLEN, 0)) > 0)  
    30.         write(STDOUT_FILENO, buf, n);  
    31.     if (n < 0)  
    32.         err_sys("recv error");  
    33. }  
    34.   
    35. int main(int argc, char *argv[])  
    36. {  
    37.     struct addrinfo *aip, *ailist;  
    38.     struct addrinfo hint;  
    39.     int     err, sockfd;  
    40.   
    41.     if (argc != 2)   
    42.         err_quit("Usage: ruptime hostname");  
    43.     hint.ai_family      = 0;  
    44.     hint.ai_flags       = 0;//AI_CANONNAME;  
    45.     hint.ai_socktype    = SOCK_STREAM;  
    46.     hint.ai_protocol    = 0;  
    47.     hint.ai_addrlen     = 0;  
    48.     hint.ai_canonname   = NULL;  
    49.     hint.ai_addr        = NULL;  
    50.     hint.ai_next        = NULL;  
    51.   
    52.     if ((err = getaddrinfo(argv[1], "ruptime", &hint, &ailist)) != 0)  
    53.         err_quit("getaddrinfo:%s", gai_strerror(err));  
    54.     for (aip = ailist; aip != NULL; aip = aip->ai_next) {  
    55.         if ((sockfd = socket(aip->ai_family, SOCK_STREAM, 0)) < 0) {  
    56.             err = errno;  
    57.         }  
    58.         if (connect_retry(sockfd, aip->ai_addr, aip->ai_addrlen) < 0)  
    59.             err = errno;  
    60.         else {  
    61.             printf("connect to ruptime server successfully ! ");  
    62.             print_uptime(sockfd);  
    63.             exit(0);  
    64.         }  
    65.     }  
    66.     fprintf(stderr, "cannot connect to %s:%s ", argv[1], strerror(err));  
    67.     exit(1); //err happened  
    68. }  
    [cpp] view plaincopy在CODE上查看代码片派生到我的代码片
     
    1. //16-15.c即服务端  
    2. #include "apue.h"  
    3. #include <netdb.h>  
    4. #include <syslog.h>  
    5. #include <errno.h>  
    6. #include <sys/socket.h>  
    7.   
    8. #define BUFLEN  128  
    9. #define QLEN    10  
    10.   
    11. #ifndef HOST_NAME_MAX  
    12. #define HOST_NAME_MAX 256  
    13. #endif  
    14.   
    15. int init_server(int type, struct sockaddr *addr, socklen_t alen, int qlen)  
    16. {  
    17.     int fd, err = 0;  
    18.   
    19.     if ((fd = socket(addr->sa_family, type, 0)) < 0)   
    20.         return -1;  
    21.     if (bind(fd, addr, alen) < 0) {  
    22.         err = errno;  
    23.         goto errout;  
    24.     }  
    25.     if (type == SOCK_STREAM || type == SOCK_SEQPACKET) {  
    26.         if (listen(fd, QLEN) < 0) {  
    27.             err = errno;  
    28.             goto errout;  
    29.         }  
    30.     }  
    31.     return fd;      //successful when prog arrive here.  
    32.   
    33. errout:  
    34.     close(fd);      //exit with failuare  
    35.     errno = err;  
    36.     return -1;  
    37. }  
    38.   
    39. void serve(int fd)  
    40. {  
    41.     char    buf[BUFLEN];  
    42.     int     clfd;  
    43.     FILE    *fp;  
    44.   
    45.     for ( ; ; ) {  
    46.         if ((clfd = accept(fd, NULL, NULL)) < 0) {  
    47.             syslog(LOG_ERR, "ruptime: accept error:%s", strerror(errno));  
    48.             exit(1);  
    49.         }  
    50.         if ((fp = popen("/usr/bin/uptime", "r")) == NULL) {  
    51.             sprintf(buf, "error:%s ", strerror(errno));  
    52.             send(clfd, buf, strlen(buf), 0);  
    53.         } else {  
    54.             while (fgets(buf, BUFLEN, fp) != NULL)  
    55.                 send(clfd, buf, strlen(buf), 0);  
    56.             pclose(fp);  
    57.         }  
    58.         close(clfd); //send end  
    59.     }  
    60. }  
    61.   
    62. int main(int argc, char *argv[])  
    63. {  
    64.     struct addrinfo *ailist, *aip;  
    65.     struct addrinfo hint;  
    66.     int     err, sockfd, n;  
    67.     char    *host;  
    68.   
    69.     if (argc != 1)  
    70.         err_quit("Usage:service");  
    71.   
    72. #ifdef _SC_HOST_NAME_MAX  
    73.     n = sysconf(_SC_HOST_NAME_MAX);  
    74.     if (n < 0)  
    75. #endif  
    76.         n = HOST_NAME_MAX;  
    77.     host = malloc(n);  
    78.     if (!host)  
    79.         err_sys("malloc error");  
    80.     if (gethostname(host, n) < 0)  
    81.         err_sys("gethostname");  
    82.     printf("host name is:%s ", host);  
    83.     daemonize("ruptimed");  
    84.   
    85.     hint.ai_flags       = AI_CANONNAME;  
    86.     hint.ai_family      = 0;  
    87.     hint.ai_socktype    = SOCK_STREAM;  
    88.     hint.ai_protocol    = 0;  
    89.     hint.ai_addrlen     = 0;  
    90.     hint.ai_canonname   = NULL;  
    91.     hint.ai_addr        = NULL;  
    92.     hint.ai_next        = NULL;  
    93.   
    94.     if ((err = getaddrinfo(host, "ruptime", &hint, &ailist)) != 0) {  
    95.         syslog(LOG_ERR , "ruptime:getaddrinfo error:%s", gai_strerror(err));  
    96.         exit(1);  
    97.     }  
    98.   
    99.     for (aip = ailist; aip != NULL; aip = aip->ai_next) {  
    100.         sockfd = init_server(SOCK_STREAM, aip->ai_addr, aip->ai_addrlen, QLEN);   
    101.         if (sockfd >= 0){  
    102.             serve(sockfd);  
    103.             exit(0);  
    104.         }  
    105.     }  
    106.     exit(1);  
    107. }  

    分别编译成可执行文件,然后运行服务端 ./ruptimed,可以通过/var/log/syslog看到发生了错误

    Servname not supported for ai_socktype .

    解决方法之一:先到/etc/services中添加如下内容

    ruptime 4000/tcp

    保存离开,但是你要确保4000这个端口没有被其他服务占用,否则改用其他端口。这时先运行

    $./ruptimed

    这是16-15编译出的名字,可以通过ps -ef 看到刚才的程序已成为后台程序,再运行

    $./ruptime ubuntu

    前面那个是16-14编译出的名字,后面那个是用户/主机名(前面有篇文章讲到了,但是这里不能用localhost或127.0.0.1

    得到结果。

    12:06:45 up 21:40,  2 users,  load average: 0.00, 0.01, 0.05

    很兴奋有木有!

    还有一种方法不用更改/etc/services的方法,是将程序中的服务名改成端口号,然后改些其他内容,详见参考文章!

    顺便提醒自己一句:在你不能保证自己程序的正确性时(即便编译通过不能代表没有写错或写漏一些东西),先不要到处找程序之外的任何原因,谨记!

  • 相关阅读:
    linux下使用kermi续
    关于vhdl中integer消耗资源的一些讨论
    linux时间编程
    Linux下C编程文件编程
    C语言I博客作业04
    C语言I博客作业02
    C语言I博客作业02
    第一周作业
    php 面向对象
    php 面向对象封装和继承
  • 原文地址:https://www.cnblogs.com/wuchanming/p/4039156.html
Copyright © 2011-2022 走看看