I/O多路转接之epoll模型

epoll是性能最好的没有之一
epoll有三个系统调用函数
epoll_create 创建文件描述符、来标识epoll模型
epoll_ctl
epoll_wait
这里写图片描述

#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、采用内存映射机制,少了数据的拷贝。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值