epoll 的使用

linux c 多路复用IO 之epoll函数

#include <stdio.h>

#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/epoll.h>
#include <sys/wait.h>
#include <netinet/in.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/types.h>
#ifndef PORT
#define PORT 8898
#endif


#ifndef MAXEPOLL
#define MAXEPOLL 2000
#endif
/*
epoll的用法
1.epoll_create 创建epoll句柄
2.用新建的server socket fd 填充struct event
3.epoll_ctl 将填充的server socket fd 加入队列
4.epoll_wait 阻塞或非阻塞轮询内核事件通知
5.判断事件是连接,或读写调用处理函数处理
*/
int setnonblock(int sockfd)
{
    if (fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFD, 0)|O_NONBLOCK) == -1){
        return -1;
    }
    return 0;
}


void handle(int sockfd){
char readbuf[1024];
char writebuf[1024];
int len;
while(1){
len = read(sockfd,readbuf,sizeof(readbuf));
if(len > 0){
printf("server accept %s\n",readbuf);
printf("response:");
fgets(writebuf,sizeof(writebuf),stdin);
write(sockfd,writebuf,sizeof(writebuf));
}
}
close(sockfd);
}
int main(int argc,char* argv[]){
int servfd,cliefd,kdpfd,currfd,nfds,n;
struct sockaddr_in servaddr,clieaddr;
struct epoll_event ev;/*此epoll_event 的作用是把server socket fd 加入到epoll中*/
struct epoll_event events[MAXEPOLL];/*此后fd上的所有事件都被添加到此events中*/
printf("set resource parameter success!\n");
if((servfd = socket(PF_INET,SOCK_STREAM,0)) == -1){
 printf("create server socket error %s\n",strerror(errno));
 exit(-1);
}
 printf("create server socket fd sucess!\n");


 setnonblock(servfd);
 bzero(&servaddr,sizeof(struct sockaddr_in));
 /**initiliza the sockaddr*/
 servaddr.sin_family = PF_INET;
 servaddr.sin_addr.s_addr = INADDR_ANY;
 servaddr.sin_port = htons(PORT);


 if(bind(servfd,(struct sockaddr*)&servaddr,sizeof(struct sockaddr_in)) == -1){
  printf("bind error: %s\n",strerror(errno));
  exit(-2);
  }
 listen(servfd,2);
 printf("epoll server listen 8898......\n");
 int len = sizeof(struct sockaddr_in);
 /*创建epoll句柄*/
 kdpfd = epoll_create(MAXEPOLL);
 /*server socket fd 支持ET的工作方式*/
 ev.events = EPOLLIN|EPOLLET;
 /*填充fd*/
 ev.data.fd = servfd;
  /*把server socket fd加入到epoll监控轮询队列中*/
  if(epoll_ctl(kdpfd,EPOLL_CTL_ADD,servfd,&ev) < 0){
  printf("add the socket fd to the epoll error %s\n",strerror(errno));
  exit(-4);
                                                   }
  printf("add server socket fd to epoll success!\n");
  currfd = 1;
   for(;;){
   /*blocking  and receive the ready event fd*/
   nfds = epoll_wait(kdpfd,events,currfd,-1);
   if(nfds  == -1){
   printf("epoll_wait error %s\n",strerror(errno));
   break;
   }
   printf("%d waiting \n",nfds);
   for(n = 0;n<nfds;++n){
    printf("events[n].data.fd: %d,socket fd %d\n",events[n].data.fd,servfd);
    /*this is the connection event*/
    if(events[n].data.fd == servfd)
    {
     cliefd = accept(servfd,(struct sockaddr*)&clieaddr,&len);
     if(cliefd == -1){
       printf("accept connect error %s\n",strerror(errno));
       continue;
     }else{
         const char* ip = (const char*)inet_ntoa(clieaddr.sin_addr);
        printf("accept connect form %s\n",ip);
          }
       setnonblock(cliefd);
       ev.events = EPOLLIN|EPOLLOUT|EPOLLET;
       ev.data.fd = cliefd;
       if(epoll_ctl(kdpfd,EPOLL_CTL_ADD,cliefd,&ev) == -1){
         printf("add the client fd to the epoll error %s\n",strerror(errno));
         continue;
                                                          }
       currfd++;
     }else{
         handle(events[n].data.fd);
         epoll_ctl(kdpfd,EPOLL_CTL_DEL,events[n].data.fd,&ev);
         currfd--;
         }
             }//for(n = 0;n<nfds;++n)
  }//for(;;)
 close(kdpfd);
 close(servfd);


return (0);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值