欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

I/O多路转接之epoll模型

程序员文章站 2022-06-14 14:40:44
...

epoll是性能最好的没有之一
epoll有三个系统调用函数
epoll_create 创建文件描述符、来标识epoll模型
epoll_ctl
epoll_wait
I/O多路转接之epoll模型

#include<stdio.h>
#include <sys/epoll.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include<arpa/inet.h>
#include<netinet/in.h>
#include<string.h>
#include<unistd.h>
#include<stdlib.h>
#define SIZE 64
static void Usage(char*proc)
{
    printf("%s [local_ip] [local_port]\n",proc);
}
int startUp(char*ip,int port)
{
   int sock=socket(AF_INET,SOCK_STREAM,0);
    if(sock<0)
    {
        perror("socket");
        exit(2);
    }
    int opt=1;
    setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));
    struct sockaddr_in server;
    server.sin_family=AF_INET;
    server.sin_port=htons(atoi(port));
    server.sin_addr.s_addr=inet_addr(ip);
    if(bind(sock,(struct sockaddr*)&server,sizeof(struct sockaddr_in))<0)
    {
        perror("bind");
        exit(3);
    }
    if(listen(sock,10)<0)
    {
        perror("listen");
        exit(4);
    }
    return sock;
}
int main(int argv,char*argc[])
{
    if(argv!=3)
    {
        Usage(argc[0]);
        return 1;
    }
    int listen_sock=startUp(argc[1],argc[2]);
    int epfd= epoll_create(256);
    if(epfd<0)
    {
       perror("epoll_create");
       return 5;
    }
    struct epoll_event ev;
    ev.events=EPOLLIN;
    ev.data.fd=listen_sock;
    epoll_ctl(epfd,EPOLL_CTL_ADD,listen_sock,&ev);
    struct epoll_event revs[64];  
    int nums=-1;
    int timeout=5000;
    while(1)
    {
        switch((nums=epoll_wait(epfd,revs,SIZE,timeout)))
        {
           case -1:
               perror("epoll_wait");
               return 6;
           case 0:
               printf("timeout\n");
               break;
            default:
               {
               int i=0;
               for(i=0;i<nums;i++)
               {
                   printf("nums %d\n",nums);
                   int fd=revs[i].data.fd;
                   if(fd==listen_sock&&revs[i].events&EPOLLIN)
                   {
                          struct sockaddr_in client;
                          socklen_t len=sizeof(client);
                          int newsock=accept(listen_sock,(struct sockaddr*)&client,&len);
                          if(newsock<0)
                          {
                              perror("accept");
                              continue;
                          }
                          printf("get a client [%s] [%d]\n",inet_ntoa(client.sin_addr),ntohs(client.sin_port));
                          ev.events=EPOLLIN;
                          ev.data.fd=newsock;
                          epoll_ctl(epfd,EPOLL_CTL_ADD,newsock,&ev);
                   }
                else if(fd!=listen_sock)
                   {
                       printf("hahah\n");
                       if(revs[i].events&EPOLLIN)
                       {
                          char buf[1024];
                          ssize_t s=read(fd,buf,sizeof(buf)-1);
                          if(s>0)
                          {
                              buf[s]=0;
                              printf("client say:%s\n",buf);
                              ev.events=EPOLLOUT;
                              ev.data.fd=fd;
                              epoll_ctl(epfd, EPOLL_CTL_MOD,fd,&ev);
                          }
                          else if(s==0)
                          {
                              printf("client is quit\n");
                              close(fd);
                              epoll_ctl(epfd,EPOLL_CTL_DEL,fd,&ev);
                          }
                          else
                          {
                              perror("read");
                              close(fd);
                              epoll_ctl(epfd,EPOLL_CTL_DEL,fd,&ev);                       }
                       }
                       else if(revs[i].events&EPOLLOUT)
                       {
                             const char* msg = "HTTP/1.1 200 OK\r\n\r\n<html><h1>Hello epoll!</h1></html>";
                              write(fd,msg,strlen(msg));
                              close(fd);
                              epoll_ctl(epfd,EPOLL_CTL_DEL,fd,&ev);

                       }
                       else
                       {

                       }
                   }
                   else
                   {

                   }
               }
               }
             break;
        }

    }
    return 0;
}

epolls是一种高性能服务器。
1、他底层的红黑树能够高效的进行增删改查
2、采用回调机制不需要轮询
3、一旦关心的文件描述符上对应的事件发生就**放入就绪队列
4、上层直接从就绪队列中取
5、就绪队列连续并且返回值是实际就绪的个数,这样即使需要遍历也会遍历的都是有效的
6、采用内存映射机制,少了数据的拷贝。

相关标签: io epoll