udp & tcp 对epoll的共用

来源:互联网 发布:微课制作软件 免费版 编辑:程序博客网 时间:2024/06/14 00:00

http://blog.csdn.net/lipengfei634626165/article/details/8136715

epoll 可以同时监听UDP 和 TCP的链接。以下为用EPOLL进行的UDP和TCP的共同监听。以下为服务器端server.c

[cpp] view plaincopy
  1. #include <stdio.h>  
  2. #include <stdlib.h>  
  3. #include <errno.h>  
  4. #include <string.h>  
  5. #include <sys/types.h>  
  6. #include <netinet/in.h>  
  7. #include <sys/socket.h>  
  8. #include <sys/wait.h>  
  9. #include <unistd.h>  
  10. #include <arpa/inet.h>  
  11. #include <fcntl.h>  
  12. #include <sys/epoll.h>  
  13. #include <sys/time.h>  
  14. #include <sys/resource.h>  
  15.   
  16.   
  17. #define MAXLINE 100  
  18. #define OPEN_MAX 100  
  19. #define LISTENQ 20  
  20. #define SERV_TPORT 5000  
  21. #define SERV_UPORT 5001  
  22.   
  23. #define INFTIM 1000  
  24.   
  25.   
  26. int setnonblocking(int sockfd)  
  27. {  
  28.     if (fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFD, 0)|O_NONBLOCK) == -1)  
  29.     {  
  30.         return -1;  
  31.     }  
  32.     return 0;  
  33. }  
  34.   
  35. int main(int argc, char* argv[])  
  36. {  
  37.     int i, tfd_listener, connfd, ufd_listener, sockfd,epfd,nfds, portnumber;  
  38.     ssize_t n;  
  39.     char line[MAXLINE] = "abcdefg";  
  40.     socklen_t clilen;  
  41.   
  42.     int count = 0;  
  43.   
  44.     struct epoll_event ev,events[20];  
  45.     struct sockaddr_in clientaddr;  
  46.     struct sockaddr_in serveraddr;  
  47.     struct sockaddr_in my_addr;  
  48.   
  49.     tfd_listener = socket(AF_INET, SOCK_STREAM, 0);  
  50.     if(tfd_listener < 0)  
  51.         perror("tfd_listener create error\n");  
  52.   
  53.     ufd_listener = socket(PF_INET,  SOCK_DGRAM, 0);  
  54.     if(ufd_listener < 0)  
  55.         perror("ufd_listener create error\n");  
  56.       
  57.     int opt=SO_REUSEADDR;  
  58.     setsockopt(ufd_listener,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));  
  59.   
  60.     setnonblocking(ufd_listener);  
  61.     setnonblocking(tfd_listener);  
  62.   
  63.     bzero(&my_addr, sizeof(my_addr));  
  64.     my_addr.sin_family = PF_INET;  
  65.     my_addr.sin_port = htons(4000);  
  66.     my_addr.sin_addr.s_addr = INADDR_ANY;  
  67.   
  68.   
  69.     bzero(&serveraddr, sizeof(serveraddr));  
  70.     serveraddr.sin_family = AF_INET;  
  71.     serveraddr.sin_addr.s_addr = INADDR_ANY;  
  72.     serveraddr.sin_port=htons(1235);  
  73.   
  74.     if (bind(ufd_listener, (struct sockaddr *) &my_addr, sizeof(struct sockaddr)) == -1)  
  75.         perror("ufd_listener bind error\n");  
  76.   
  77.     if(bind(tfd_listener,(struct sockaddr *)&serveraddr, sizeof(struct sockaddr))== -1)  
  78.         perror("tfd_listener bind error\n");  
  79.   
  80.     epfd=epoll_create(256);  
  81.   
  82.     ev.data.fd=tfd_listener;  
  83.     ev.events=EPOLLIN|EPOLLET;    
  84.     epoll_ctl(epfd,EPOLL_CTL_ADD,tfd_listener,&ev);  
  85.   
  86.     ev.data.fd = ufd_listener;  
  87.     ev.events = EPOLLIN|EPOLLET;  
  88.     epoll_ctl(epfd,EPOLL_CTL_ADD,ufd_listener,&ev);  
  89.   
  90.     listen(tfd_listener, LISTENQ);  
  91.   
  92.     for ( ; ; ) {  
  93.   
  94.         nfds=epoll_wait(epfd,events,20,500);  
  95.   
  96.         printf("wait end nfds = %d\n",nfds);  
  97.   
  98.         for(i=0;i<nfds;++i)  
  99.         {  
  100.             if(events[i].data.fd == tfd_listener)  
  101.             {  
  102.                 connfd = accept(tfd_listener,(struct sockaddr *)&clientaddr, &clilen);  
  103.                 if(connfd<0){  
  104.                     perror("connfd<0");  
  105.                     exit(1);  
  106.                 }  
  107.                 setnonblocking(connfd);  
  108.                 char *str = inet_ntoa(clientaddr.sin_addr);  
  109.                     printf("accept a connection from %s\n", str);  
  110.   
  111.                     ev.data.fd=connfd;  
  112.                     ev.events=EPOLLIN|EPOLLET;  
  113.                     epoll_ctl(epfd,EPOLL_CTL_ADD,connfd,&ev);  
  114.   
  115.             }  
  116.             else if(events[i].data.fd == ufd_listener)  
  117.             {  
  118.                 printf("udp\n");  
  119.                 if( events[i].events && EPOLLIN )  
  120.                     printf( "udp receive begin!\n" );  
  121.                 n = recvfrom(ufd_listener, line,MAXLINE, 0,  
  122.                                              (struct sockaddr *)&clientaddr, &clilen);                
  123.                 if(n < 0)  
  124.                     perror( "udp receive ERROR\n" );  
  125.                 else  
  126.                     printf( "udp receive right!\n" );  
  127.           
  128.             }  
  129.             else if(events[i].events&EPOLLIN)//如果是已经连接的用户,并且收到数据,那么进行读入。  
  130.                 {  
  131.                 printf("count == %d\n",count);  
  132.                 count ++;  
  133.                     if ( (sockfd = events[i].data.fd) < 0)  
  134.                         continue;  
  135.                     if ( (n = read(sockfd, line, MAXLINE)) < 0) {  
  136.                         if (errno == ECONNRESET) {  
  137.                                 close(sockfd);  
  138.                                 events[i].data.fd = -1;  
  139.                         }   
  140.                     else  
  141.                                 printf("readline error\n");  
  142.                     }   
  143.                 else if (n == 0) {  
  144.                     printf("close tcp port\n");  
  145.                     close(sockfd);  
  146.                         events[i].data.fd = -1;  
  147.                 }  
  148.                 else  
  149.                 {  
  150.                     printf("read OK %s\n", line);  
  151.                         line[n] = '/0';  
  152.                     }             
  153.                     ev.data.fd=sockfd;  
  154.                     ev.events=EPOLLOUT|EPOLLET;  
  155.                     epoll_ctl(epfd,EPOLL_CTL_ADD,connfd,&ev);                 
  156.         }else if(events[i].events&EPOLLOUT) // 如果有数据发送  
  157.   
  158.             {  
  159.                 printf("write \n");  
  160.                 sockfd = events[i].data.fd;  
  161.                 write(sockfd, line, n);  
  162.                 //设置用于读操作的文件描述符  
  163.   
  164.                 ev.data.fd=sockfd;  
  165.                 //设置用于注测的读操作事件  
  166.   
  167.                 ev.events=EPOLLIN|EPOLLET;  
  168.                 //修改sockfd上要处理的事件为EPOLIN  
  169.   
  170.                 epoll_ctl(epfd,EPOLL_CTL_MOD,sockfd,&ev);  
  171.             }  
  172.         }  
  173.     }  
  174.     return 0;  
  175. }  

下面是udp客户端 udp_client.c的实现

[cpp] view plaincopy
  1. #include <sys/types.h>  
  2. #include <sys/socket.h>  
  3. #include <string.h>  
  4. #include <netinet/in.h>  
  5. #include <stdio.h>  
  6. #include <stdlib.h>  
  7. #include <arpa/inet.h>  
  8. #include <unistd.h>  
  9.   
  10. #define MAXLINE 1024  
  11. #define SERV_PORT 4000  
  12.   
  13. void do_cli(FILE *fp, int sockfd, struct sockaddr *pservaddr, socklen_t servlen)  
  14. {  
  15.     int n;  
  16.     char sendline[MAXLINE], recvline[MAXLINE + 1];  
  17.   
  18.   
  19.     if(connect(sockfd, (struct sockaddr *)pservaddr, servlen) == -1)  
  20.     {  
  21.         perror("connect error");  
  22.         exit(1);  
  23.     }  
  24.     else  
  25.     {  
  26.         printf("connect OK\n");  
  27.     }  
  28.   
  29.     fgets(sendline, MAXLINE, fp);  
  30.     n = write(sockfd, sendline, strlen(sendline)-1);  
  31.     if ( n <= 0)  
  32.         perror("write error\n");  
  33.     printf("write %s \n",sendline);  
  34.           
  35. }  
  36.   
  37. int main(int argc, char **argv)  
  38. {  
  39.     int sockfd;  
  40.     struct sockaddr_in servaddr;  
  41.   
  42.     bzero(&servaddr, sizeof(servaddr));  
  43.     servaddr.sin_family = AF_INET;  
  44.     servaddr.sin_port = htons(SERV_PORT);  
  45.     inet_aton("127.0.0.1",&(servaddr.sin_addr));  
  46.   
  47.     sockfd = socket(AF_INET, SOCK_DGRAM, 0);  
  48.   
  49.     do_cli(stdin, sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr));  
  50.   
  51.     return 0;  
  52. }  
下面是TCP 的客户端tcp_client.c的实现

[cpp] view plaincopy
  1. #include <stdio.h>  
  2. #include <sys/socket.h>  
  3. #include <sys/epoll.h>  
  4. #include <netinet/in.h>  
  5. #include <arpa/inet.h>  
  6. #include <fcntl.h>  
  7. #include <unistd.h>  
  8. #include <errno.h>  
  9. #include <stdlib.h>  
  10. #include <string.h>  
  11. #include <errno.h>  
  12.   
  13. int main(){  
  14.     int fd;  
  15.     struct sockaddr_in clientaddr;  
  16.     char  recvline[1000] = "abcdef";  
  17.     int n = 0;  
  18.     if((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)  
  19.         perror("socket create error");  
  20.       
  21.     bzero(&clientaddr, sizeof(clientaddr));  
  22.     clientaddr.sin_family = AF_INET;  
  23.     inet_aton("127.0.0.1",&(clientaddr.sin_addr));  
  24.     clientaddr.sin_port = htons(1235);  
  25.   
  26.     if(connect(fd, (struct sockaddr *)&clientaddr,sizeof(clientaddr)) < 0)  
  27.         perror("connect error");  
  28.     printf("%d\n",fd);  
  29.     while((n = write(fd, recvline,6))>0){  
  30.         printf("recvline = %s",recvline);  
  31.         if(n > 0)  
  32.             break;  
  33.     }  
  34.     if (n < 0)  
  35.         perror("write error");  
  36.   
  37.     exit(0);  
  38. }  

0 0