《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 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章