27
2017
09

epoll高级应用之同时处理 tcp/udp 的服务器

理论

同一个 ip+port可以同时的被tcp模块使用也可以同时被udp模块使用。它可以同时处理来自不同运输层协议的请求。当不同的数据到达时,应用只需在不同的缓存队列中读取数据即可。

这里写图片描述

/*server*/
#include<stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include<assert.h>
#include<netinet/in.h>
#include<errno.h>
#include<string.h>
#include<stdlib.h>
#include<sys/epoll.h>
#include<pthread.h>


#define EVENT_LENGTH 1024
#define TCP_BUFFER 1024
#define UDP_BUFFER 1024

int setnonblock(int fd)
{
    int old_option=fcntl(fd,F_GETFL);
   int new_option=old_option|O_NONBLOCK;
   fcntl(fd,F_SETFL,new_option);
   return fd;
}
void add_event(int epoll_fd,int fd)
{
   struct  epoll_event event;
     event.events=EPOLLIN|EPOLLET;
     event.data.fd=fd;
     epoll_ctl(epoll_fd,EPOLL_CTL_ADD,fd,&event);
     setnonblock(fd);
}
int startup(char * ip,char *port)
{
   int listen_sock=0;
   if((listen_sock=socket(AF_INET,SOCK_STREAM,0))<0)
    {
          perror("listen");
          exit(1);
    }
        }
  struct sockaddr_in address;
   bzero(&address,sizeof(address));
   address.sin_family=AF_INET;
   address.sin_port=htons(atoi(port));
   int ret=0;
   if((ret=inet_pton(AF_INET,ip,&address.sin_addr))==0)
    {
       printf(" ip ge shi cuowu\n");
       exit(2);
    }
   else if(ret<0)
    {
       perror("inet_pton");
       exit(3);
    }
   if(bind(listen_sock,(const struct sockaddr*)&address,sizeof(address))==-1)
   {
        perror("bind");
                exit(4);
   }
   if(listen(listen_sock,100)<-1)
   {
       perror("listen");
       exit(5);
   }
   return listen_sock;
}
int udp_server(char*ip,char*port)
{
   int udp=0;
   if((udp=socket(AF_INET,SOCK_DGRAM,0))<0)
    {
          perror("udp");
          exit(6);
    }
   struct sockaddr_in address;
   bzero(&address,sizeof(address));
   address.sin_family=AF_INET;
   address.sin_port=htons(atoi(port));
     int ret=0;
   if((ret=inet_pton(AF_INET,ip,&address.sin_addr))==0)
    {
       printf(" ip ge shi cuowu\n");
       exit(7);
    }
   else if(ret<0)
    {
       perror("inet_pton");
       exit(8);
    }
   if(bind(udp,(const struct sockaddr*)&address,sizeof(address))==-1)
   {
        perror("bind");
        exit(9);
   }
   return udp;
}
int main(int argc,char*argv[])
{
   if(argc!=3)
   {
     printf("error input\n");
     exit(6);
   }
  int listen=startup(argv[1],argv[2]);
  int udp=udp_server(argv[1],argv[2]);
 struct epoll_event events[EVENT_LENGTH];
  int epoll_fd=epoll_create(5);
  assert(epoll_fd!=-1);
  add_event(epoll_fd,listen);
  add_event(epoll_fd,udp);
  char udp_buff[UDP_BUFFER];
  memset(udp_buff,0,UDP_BUFFER);
  char tcp_buff[TCP_BUFFER];
  memset(tcp_buff,0,TCP_BUFFER);
  while(1)
  {
     int number=epoll_wait(epoll_fd,events,10,-1);
     if(number<0)
             printf("epoll wait fail\n");
        break;
     }
     int i=0;
    for( i=0;i<number;++i)
    {
       int sockfd=events[i].data.fd;
       if(sockfd==listen)
       {
         while(1)
         {
           struct sockaddr_in client;
           socklen_t len=sizeof(client);
           int peer=accept(sockfd,(struct sockaddr *)&client,&len);
           if(peer==-1&&(errno==EAGAIN||errno==EWOULDBLOCK))
               break;
           printf("peer ip:%s \t port:%d \n",inet_ntoa(client.sin_addr),ntohs(client.sin_port));
           add_event(epoll_fd,peer);
                     bzero(&client,sizeof(client));
         }
       }
       else if(sockfd==udp)
       {
          struct sockaddr_in client_address;
          socklen_t len=sizeof(client_address);
          int size=recvfrom(sockfd,udp_buff,UDP_BUFFER-1,0,(struct sockaddr *)&client_address,&len);
          udp_buff[size]=0;
          printf("udp client say# %s",udp_buff);
          fflush(stdout);
          printf("please enter#");
          fflush(stdout);
          size=read(0,udp_buff,1024);
          udp_buff[size]=0;
          sendto(sockfd,udp_buff,UDP_BUFFER-1,0,(struct sockaddr*)&client_address,len);
      }else if(events[i].events&EPOLLIN)
      {
                printf("tcp client say#:");
        int size=0;
          while(1)
       {
           size=recv(sockfd,tcp_buff,1024,0);
          if(size==-1)
          {
              if(errno==EAGAIN||errno==EWOULDBLOCK)
                   break;
               close(sockfd);
               break;
          }else if(size==0)
           {
                close(sockfd);
                printf("tcp disconnect");
                goto pos;
           }
          tcp_buff[size]=0;
          printf("%s",tcp_buff);
          fflush(stdout);
                 }
        printf("please Enter#");
        fflush(stdout);
        size=read(0,tcp_buff,1024);
        tcp_buff[size]=0;
        send(sockfd,tcp_buff,size,0);
      }else {
       printf("something happened \n");
     }
     pos:
       printf("\n");
    }
 }
 close(listen);
 return 0;
}

/*tcp_client*/ 
#include<stdio.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<stdlib.h>
#include<string.h>
int main(int argv,const char*arg[])
{
   int req_sock=socket(AF_INET,SOCK_STREAM,0);
   struct sockaddr_in sock_in;
   sock_in.sin_family=AF_INET;
   sock_in.sin_port=  htons(atoi(arg[2]));
   sock_in.sin_addr.s_addr=inet_addr(arg[1]);
   socklen_t len=sizeof(sock_in);
   connect(req_sock,(struct sockaddr*)&sock_in,len);
   char buf[1024];
   memset(buf,0,1024);
   while(1)
   {
     printf("please Enter:");
     fflush(stdout);
     ssize_t s=read(0,buf,sizeof(buf));
     buf[s]=0;
     s=write(req_sock,buf,s);
     if(s<0)
      {
      perror("write");
      exit(1);
     }
     s=read(req_sock,buf,sizeof(buf));
     if(s>0)
     {
       buf[s]=0;
       if(strcmp(buf,"quit")==0)break;
       printf("server say:%s",buf);
       fflush(stdout);
     }
   }
   return 0;
   close(req_sock);
}
/*udp_client*/ 
#include<stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include<stdlib.h>
int main(int argc,char*argv[])
{
   if(argc!=3)
   {
     printf("please enter ip port\n");
     exit(1);
   }
   int sock=socket(AF_INET,SOCK_DGRAM,0);
   char buff[1024];
   struct sockaddr_in server;
   server.sin_family=AF_INET;
   server.sin_port=htons(atoi(argv[2]));
   server.sin_addr.s_addr=inet_addr(argv[1]);
   socklen_t len=sizeof(struct sockaddr_in);
   int size=0;
   while(1){
   printf("please Enter #");
   fflush(stdout);
   size=read(0,buff,1024);
   buff[size]=0;
   sendto(sock,buff,1024,0,(struct sockaddr*)&server,len);
   size=recvfrom(sock,buff,1024,0,(struct sockaddr*)&server,&len);
   buff[size]=0;
   printf("server say#%s",buff);
  }
  return 0;
}

这里写图片描述

上一篇:iOS中TextField只能输入数字且小数点后最多输入两位 下一篇:浅谈RecyclerView性能问题 滑动卡顿 界面闪动