开发者社区> 科技小能手> 正文

《UNIX网络编程》中第一个timer_server的例子

简介:
+关注继续查看

 1.配置环境

    在这里下载unpv13e.tar.gz,其中包含了《UNIX网络编程》第一卷的源代码。假设将其移到~/Unix/Network/目录下,以下为配置过程(假设当前目录为下载目录):


  1. mv ./unpv13e.tar.gz ~/Unix/Network 
  2.  
  3.     cd ~/Unix/Network
  4.  
  5.     tar -zxvf unpv13e.tar.gz 
  6.  
  7.     cd unpv13e
  8.  
  9.     ./configure 
  10.  
  11.     cd lib 
  12.  
  13.     make 
  14.  
  15.     cd ../                  #back to unpv13e/ 
  16.  
  17.     cp libunp.a /usr/lib 
  18.  
  19.     cp libunp.a /usr/lib64
  20.  
  21.     cd ../                  #back to Network/ 
  22.  
  23.     cp ./unpv13e/lib/unp.h ./ 
  24.  
  25.     cp ./unpv13e/config.h ./ 
  26.  
  27.     vi unp.h #使用vi将unp.h中的 #include "../config.h"改为#include "./config.h" 
  28.  
  29.     mkdir timer_server 
  30.  
  31.     cd timer_server 

2.编写代码    

 编写服务端代码:


  1. #include "../unp.h" 
  2.  
  3. int main(int argc,char *argv[]) 
  4.     int listenfd,connfd; 
  5.     struct sockaddr_in servaddr; 
  6.     char buff[MAXLINE]; 
  7.     time_t ticks; 
  8.     listenfd = Socket(AF_INET,SOCK_STREAM,0); 
  9.     bzero(&servaddr,sizeof(servaddr)); 
  10.     servaddr.sin_family = AF_INET; 
  11.     servaddr.sin_addr.s_addr = htonl(INADDR_ANY); 
  12.     servaddr.sin_port=htons(13); 
  13.     Bind(listenfd,(SA*)&servaddr,sizeof(servaddr)); 
  14.     Listen(listenfd,LISTENQ); 
  15.     for(;;) 
  16.     { 
  17.         connfd = Accept(listenfd,(SA*)NULL,NULL); 
  18.         ticks = time(NULL); 
  19.         snprintf(buff,sizeof(buff),"%.24s\r\n",ctime(&ticks)); 
  20.         Write(connfd,buff,strlen(buff)); 
  21.         Close(connfd); 
  22.     } 
  23.     return 0; 

      编写客户端代码:


  1. #include "../unp.h" 
  2.  
  3. int main(int argc,char *argv[]) 
  4.     int socketfd,n; 
  5.     char recvline[MAXLINE+1]; 
  6.     struct sockaddr_in servaddr; 
  7.     if(argc != 2) 
  8.         err_quit("Usage:%s <IP Address>",argv[0]); 
  9.     if( (socketfd = socket(AF_INET,SOCK_STREAM,0)) <0 ) 
  10.         err_sys("socket error"); 
  11.     bzero(&servaddr,sizeof(servaddr)); 
  12.     servaddr.sin_family = AF_INET; 
  13.     servaddr.sin_port = htons(13); 
  14.     if( inet_pton(AF_INET,argv[1],&servaddr.sin_addr) <= 0) 
  15.         err_quit("inet_pton error for %s .",argv[0]); 
  16.     if(connect(socketfd,(SA*)&servaddr,sizeof(servaddr))<0) 
  17.         err_sys("connecting error."); 
  18.     while( (n = read(socketfd,recvline,MAXLINE))>0){ 
  19.         recvline[n] = 0; 
  20.         if(fputs(recvline,stdout) == EOF) 
  21.             err_sys("read error"); 
  22.     } 
  23.     if(n<0) 
  24.         err_sys("read error"); 
  25.     return 0; 

         编译运行:


  1. $gcc server.c -o server -lunp 
  2. $gcc client.c -o client -lunp 
  3. $./server & 
  4. $./client 192.168.101.71 
  5. Mon Jul 16 17:37:45 2012 
  6. $./client 192.168.101.71 
  7. Mon Jul 16 17:37:47 2012 
  8. $./client 192.168.101.71 
  9. Mon Jul 16 17:37:47 2012 
  10. $./client 192.168.101.71 
  11. Mon Jul 16 17:37:49 2012  

      在读的时候有一个小技巧,就是使用循环的方式去读套接口中的数据而不是只读一次,这是由于需要的数据可能分成多节传过来。下面的代码将展示这一点:


  1. #include "../unp.h" 
  2.  
  3. int main(int argc,char *argv[]) 
  4.     int socketfd,n; 
  5.     char recvline[MAXLINE+1]; 
  6.     struct sockaddr_in servaddr; 
  7.     if(argc != 2) 
  8.         err_quit("Usage:%s <IP Address>",argv[0]); 
  9.     if( (socketfd = socket(AF_INET,SOCK_STREAM,0)) <0 ) 
  10.         err_sys("socket error"); 
  11.     bzero(&servaddr,sizeof(servaddr)); 
  12.     servaddr.sin_family = AF_INET; 
  13.     servaddr.sin_port = htons(13); 
  14.     if( inet_pton(AF_INET,argv[1],&servaddr.sin_addr) <= 0) 
  15.         err_quit("inet_pton error for %s .",argv[0]); 
  16.     if(connect(socketfd,(SA*)&servaddr,sizeof(servaddr))<0) 
  17.         err_sys("connecting error."); 
  18.     int counter = 0; 
  19.     while( (n = read(socketfd,recvline,MAXLINE))>0){ 
  20.         recvline[n] = 0; 
  21.         if(fputs(recvline,stdout) == EOF) 
  22.             err_sys("read error"); 
  23.         counter++; 
  24.     } 
  25.     printf("read operation :%d\n",counter); 
  26.     if(n<0) 
  27.         err_sys("read error"); 
  28.     return 0; 

        在循环中加入计数代码,用来统计计数的次数。然后我们将服务器端的代码改为for循环的形式:


  1. #include "../unp.h" 
  2.  
  3. #include<string.h> 
  4. int main(int argc,char *argv[]) 
  5.     int listenfd,connfd; 
  6.     struct sockaddr_in servaddr; 
  7.     char buff[MAXLINE]; 
  8.     time_t ticks; 
  9.     listenfd = Socket(AF_INET,SOCK_STREAM,0); 
  10.     bzero(&servaddr,sizeof(servaddr)); 
  11.     servaddr.sin_family = AF_INET; 
  12.     servaddr.sin_addr.s_addr = htonl(INADDR_ANY); 
  13.     servaddr.sin_port=htons(13); 
  14.     Bind(listenfd,(SA*)&servaddr,sizeof(servaddr)); 
  15.     Listen(listenfd,LISTENQ); 
  16.     for(;;) 
  17.     { 
  18.         connfd = Accept(listenfd,(SA*)NULL,NULL); 
  19.         ticks = time(NULL); 
  20.         snprintf(buff,sizeof(buff),"%.24s\r\n",ctime(&ticks)); 
  21.         int i = 0; 
  22.         int len = strlen(buff); 
  23.         for(i=0;i<len;i++) 
  24.             Write(connfd,&buff[i],sizeof(char)); 
  25.         Close(connfd); 
  26.     } 
  27.     return 0; 

        下面为运行效果:

         


  1. $ ./client 192.168.101.71 
  2. Mon Jul 16 21:24:05 2012 
  3. read operation :4 
  4. $ ./client 192.168.101.71 
  5. Mon Jul 16 21:24:05 2012 
  6. read operation :4 
  7. $ ./client 192.168.101.71 
  8. Mon Jul 16 21:24:05 2012 
  9. read operation :3 
  10. $ ./client 192.168.101.71 
  11. Mon Jul 16 21:24:06 2012 
  12. read operation :4 
  13. $ ./client 192.168.101.71 
  14. Mon Jul 16 21:24:06 2012 
  15. read operation :3 
  16. $ ./client 192.168.101.71 
  17. Mon Jul 16 21:24:07 2012 
  18. read operation :5 

 


本文转自hipercomer 51CTO博客,原文链接:http://blog.51cto.com/hipercomer/932671


版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
unix网络编程str_cli使用epoll实现
unix网络编程str_cli使用epoll实现 unix环境高级编程中也有这个函数,都是为了讲解IO多路转接。从本质上来看epoll就是一个改善了的select和poll,本质没发生任何变化,对于构建在poll,select和epoll上的框架使用者来说,没什么区别。
679 0
Unix编程/应用问答中文版 ---6./etc/system可调资源限制
发信人: dean (叮叮当当), 信区: LinuxDev标  题: Unix编程/应用问答中文版 ---6./etc/system可调资源发信站: 飘渺水云间 (Fri Nov 22 12:02:19 2002), 转信Unix编程/应用问答中文版 ---6.
674 0
文章
问答
文章排行榜
最热
最新
相关电子书
更多
低代码开发师(初级)实战教程
立即下载
阿里巴巴DevOps 最佳实践手册
立即下载
冬季实战营第三期:MySQL数据库进阶实战
立即下载