Linux socket网络编程之聊天室(三):select异步通讯实现

来源:互联网 发布:美林数据java开发岗 编辑:程序博客网 时间:2024/05/16 17:56

1.服务器端

[cpp] view plaincopy
  1. /*select_server*/  
  2. #include <stdio.h>  
  3. #include <stdlib.h>  
  4. #include <errno.h>  
  5. #include <string.h>  
  6. #include <sys/types.h>  
  7. #include <netinet/in.h>  
  8. #include <sys/socket.h>  
  9. #include <sys/wait.h>  
  10. #include <pthread.h>  
  11. #include <sys/wait.h>  
  12. #include <sys/time.h>  
  13. #include <arpa/inet.h>  
  14. #include <unistd.h>  
  15.   
  16. #define MAXBUF 1024  
  17.   
  18. int main(int argc,char **argv){  
  19.     int sockfd,new_fd;  
  20.     socklen_t len;  
  21.     struct sockaddr_in my_addr,their_addr;  
  22.     unsigned int myport,lisnum;  
  23.     char buf[MAXBUF+1];  
  24.     fd_set rfds;  
  25.     struct timeval tv;  
  26.     int retval,maxfd = -1;  
  27.   
  28.     if(argv[1]){  
  29.         myport = atoi(argv[1]);  
  30.     }  
  31.     else  
  32.         myport = 7838;  
  33.   
  34.     if(argv[2]){  
  35.         lisnum = atoi(argv[2]);  
  36.     }  
  37.     else  
  38.         lisnum =2;  
  39.     if((sockfd = socket(PF_INET,SOCK_STREAM,0))== -1){  
  40.         perror("socket");  
  41.         exit(1);  
  42.     }  
  43.   
  44.     bzero(&my_addr,sizeof(my_addr));  
  45.     my_addr.sin_family = PF_INET;  
  46.     my_addr.sin_port = htons(myport);  
  47.     if(argv[3])  
  48.         my_addr.sin_addr.s_addr = INADDR_ANY;  
  49.       
  50.     if(bind(sockfd,(struct sockaddr *)&my_addr,sizeof(struct sockaddr)) == -1){  
  51.         perror("bind");  
  52.         exit(1);  
  53.     }  
  54.       
  55.     if(listen(sockfd, lisnum) == -1){  
  56.         perror("listen");  
  57.         exit(1);  
  58.     }  
  59.       
  60.     while(1){  
  61.         printf("\n----waiting for new connecting to start new char----\n");  
  62.         len = sizeof(struct sockaddr);  
  63.         if((new_fd = accept(sockfd,(struct sockaddr *)&their_addr,&len)) == -1){  
  64.             perror("accept");  
  65.             exit(errno);  
  66.         }  
  67.         else  
  68.             printf("server:got connection from %s,port %d,socked %d\n",\  
  69.                 inet_ntoa(their_addr.sin_addr),\  
  70.                 ntohs(their_addr.sin_port),new_fd);  
  71.           
  72.         /*开始处理每个新连接上的数据收发*/  
  73.         //printf("\n---ready to go.now you can chatting...input enter,then you can chat---\n");  
  74.         while(1){  
  75.             /*把集合清空*/  
  76.             FD_ZERO(&rfds);  
  77.             /*把标准输入句柄0加入到集合中*/  
  78.             FD_SET(0,&rfds);  
  79.             maxfd = 0;  
  80.             /*把当前连接句柄new_fd加入到集合中*/  
  81.             FD_SET(new_fd,&rfds);  
  82.             if(new_fd > maxfd)  
  83.                 maxfd = new_fd;  
  84.             /*设置最大等待时间*/  
  85.             tv.tv_sec = 1;  
  86.             tv.tv_usec = 0;  
  87.   
  88.             retval = select(maxfd+1,&rfds,NULL,NULL,&tv);  
  89.             if(retval == -1){  
  90.                 printf("select error!%s\n",strerror(errno));  
  91.                 break;  
  92.             }  
  93.             else if(retval == 0){  
  94.                 //printf("no message come,user no press the button,please wait...\n");  
  95.                 continue;  
  96.             }  
  97.             else{  
  98.   
  99.                 if(FD_ISSET(new_fd,&rfds)){  
  100.                 /*连接的socket 上有消息则接收并显示*/  
  101.                     bzero(buf,MAXBUF+1);  
  102.                     /*接收对方发过来的消息,最多MAXBUF字节*/  
  103.                     len = recv(new_fd, buf, MAXBUF, 0);  
  104.                     if(len > 0)  
  105.                         printf("recv msg success:%s! %d bytes rcv.\n ",buf,len);  
  106.                     else{  
  107.                         if(len < 0){  
  108.                             printf("recv msg fail.the errno is:%d,error info is %s.\n",errno,strerror(errno));  
  109.                         }  
  110.                         else  
  111.                             printf("quit.\n");  
  112.                         break;  
  113.                     }  
  114.                 }// FD_ISSET = sockfd情况  
  115.                 if(FD_ISSET(0,&rfds)){  
  116.                     /*用户有输入了,则读取其内容并发送*/  
  117.                     bzero(buf, MAXBUF+1);  
  118.                     fgets(buf, MAXBUF, stdin);  
  119.                     if(!strncasecmp(buf, "quit", 4)){  
  120.                         printf("self request to quit the chating\n");  
  121.                         break;  
  122.                     }  
  123.                     /*发消息给服务器*/  
  124.                     len = send(new_fd, buf, strlen(buf)-1 , 0);  
  125.                     if(len < 0){  
  126.                         printf("mgs:%s send fail!errno is:%d,error info is:%s\n", buf, errno, strerror(errno));  
  127.                         break;  
  128.                     }else{  
  129.                         printf("msg: %s\t send success, send %d bytes!\n", buf, len);  
  130.                     }  
  131.                 }//FD_ISSET = 0  
  132.               
  133.             }//select 处理结束  
  134.               
  135.         }/*内while*/  
  136.         close(new_fd);  
  137.         /*处理每个新连接上的数据收发结束*/  
  138.         printf("would you want to chatting with another one?(no->quit)");  
  139.         fflush(stdout);  
  140.         bzero(buf,MAXBUF+1);  
  141.         fgets(buf,MAXBUF,stdin);  
  142.         if(!strncasecmp(buf,"no",2)){  
  143.             printf("quit the chatting!\n");  
  144.             break;  
  145.         }  
  146.       
  147.     }/*外while*/  
  148.   
  149.     close(sockfd);  
  150.     return 0;  
  151. }  

2.客户端

[cpp] view plaincopy
  1. /*select_client.c 2011.9.2 by yyg*/  
  2. #include <stdio.h>  
  3. #include <stdlib.h>  
  4. #include <errno.h>  
  5. #include <string.h>  
  6. #include <sys/types.h>  
  7. #include <netinet/in.h>  
  8. #include <sys/socket.h>  
  9. #include <sys/wait.h>  
  10. #include <pthread.h>  
  11. #include <sys/time.h>  
  12. #include <arpa/inet.h>  
  13. #include <unistd.h>  
  14. #include <resolv.h>  
  15.   
  16. #define MAXBUF 1024  
  17. int main(int argc,char **argv){  
  18.     int sockfd,len;  
  19.     struct sockaddr_in dest;  
  20.     char buffer[MAXBUF+1];  
  21.     fd_set rfds;  
  22.     struct timeval tv;  
  23.     int retval,maxfd = -1;  
  24.   
  25.     if(argc != 3){  
  26.         printf("the param style wrong!\n");  
  27.         exit(0);  
  28.     }  
  29.     /*创建一个socket用于tcp通信*/  
  30.     if((sockfd = socket(AF_INET,SOCK_STREAM,0)) < 0){  
  31.         perror("socket");  
  32.         exit(errno);  
  33.     }  
  34.   
  35.     /*初始化服务器端(对方)的地址和端口信息*/  
  36.     bzero(&dest,sizeof(dest));  
  37.     dest.sin_family = AF_INET;  
  38.     dest.sin_port = htons(atoi(argv[2]));  
  39.     if(inet_aton(argv[1],(struct in_addr *)&dest.sin_addr.s_addr) == 0){  
  40.         perror(argv[1]);  
  41.         exit(errno);  
  42.     }  
  43.   
  44.     /*conect to the server*/  
  45.     if(connect(sockfd,(struct sockaddr*)&dest,sizeof(dest)) !=0){  
  46.         perror("connect");  
  47.         exit(errno);  
  48.     }  
  49.   
  50.     printf("\n---ready to chatting...---\n");  
  51.     while(1){  
  52.         /*把集合清空*/  
  53.         FD_ZERO(&rfds);  
  54.         /*把标准输入句柄0加入到集合中*/  
  55.         FD_SET(0,&rfds);  
  56.         maxfd = 0;  
  57.         /*把当前连接句柄socket 加入到集合中*/  
  58.         FD_SET(sockfd,&rfds);  
  59.         if(sockfd > maxfd)  
  60.             maxfd = sockfd;  
  61.         /*设置最大等待时间*/  
  62.         tv.tv_sec = 1;  
  63.         tv.tv_usec = 0;  
  64.         /*开始等待*/  
  65.         retval = select(maxfd+1,&rfds,NULL,NULL,&tv);  
  66.         if(retval == -1){  
  67.             printf("select error,quit!\n");  
  68.             break;  
  69.         }else if(retval == 0){  
  70.             continue;  
  71.         }else{  
  72.             if(FD_ISSET(sockfd,&rfds)){  
  73.                 /*连接的socket 上有消息则接收并显示*/  
  74.                 bzero(buffer,MAXBUF+1);  
  75.                 /*接收对方发过来的消息,最多MAXBUF字节*/  
  76.                 len = recv(sockfd, buffer, MAXBUF, 0);  
  77.                 if(len > 0)  
  78.                     printf("recv msg success:%s! %d bytes rcv.\n ",buffer,len);  
  79.                 else{  
  80.                     if(len < 0){  
  81.                         printf("recv msg fail.the errno is:%d,error info is %s.\n",errno,strerror(errno));  
  82.                     }  
  83.                     else  
  84.                         printf("quit.\n");  
  85.                     break;  
  86.                 }  
  87.             }// FD_ISSET = sockfd情况  
  88.             if(FD_ISSET(0,&rfds)){  
  89.                 /*用户有输入了,则读取其内容并发送*/  
  90.                 bzero(buffer, MAXBUF+1);  
  91.                 fgets(buffer, MAXBUF, stdin);  
  92.                 if(!strncasecmp(buffer, "quit", 4)){  
  93.                     printf("self request to quit the chating\n");  
  94.                     break;  
  95.                 }  
  96.                 /*发消息给服务器*/  
  97.                 len = send(sockfd, buffer, strlen(buffer)-1 , 0);  
  98.                 if(len < 0){  
  99.                     printf("mgs:%s send fail!errno is:%d,error info is:%s\n", buffer, errno, strerror(errno));  
  100.                     break;  
  101.                 }else{  
  102.                     printf("msg: %s\t send success, send %d bytes!\n", buffer, len);  
  103.                 }  
  104.             }//FD_ISSET = 0  
  105.               
  106.         }//select 处理结束  
  107.   
  108.     }//处理聊天的while 循环  
  109.     /*关闭连接*/  
  110.     close(sockfd);  
  111.     return 0;  
  112. }  

运行结果:

终端1:服务器端

[cpp] view plaincopy
  1. [root@localhost net]# ./select_server 7838  
  2.   
  3. ----waiting for new connecting to start new char----  
  4. server:got connection from 172.31.100.236,port 59462,socked 4  
  5. recv msg success:kfldsjfk! 8 bytes rcv.  
  6. 456354  
  7.  msg: 456354  
  8.          send success, send 6 bytes!  
  9. recv msg success:453455! 6 bytes rcv.  

终端2:客户端

[cpp] view plaincopy
  1. [root@localhost net]#  ./select_client 172.31.100.236 7838  
  2.   
  3. ---ready to chatting...---  
  4. kfldsjfk  
  5. msg: kfldsjfk  
  6.          send success, send 8 bytes!  
  7. recv msg success:456354! 6 bytes rcv.  
  8. 453455  
  9.  msg: 453455  
  10.          send success, send 6 bytes!  


原创粉丝点击