epoll : 进行创建epoll_event 变量ev,ev用于注册事件,数组用于回传要处理的事件*****(PS:这个很重要,数组不参与事件的注册中,它只回传需要处理的事件,相当于中介,起数据中继的作用,只需要在epoll_wait中当做参数2即可。int epoll_wait(int epfd, struct epoll_event *events,int maxevents, int timeout); 初始化变量后生成epoll专用的文件描述符--epoll_create(),注册事件 epoll_ctl(epfd,EPOLL_CTL_ADD,fd,&ev),然后就是主题for(;;)代码,进行wait阻塞等待,并处理返回的发生的事件,下面是我自己实现的并发epoll服务器实例,测试可以多个C进行连接发送。
server.h
#pragma once
#include<iostream>
#include<sys/socket.h>
#include<sys/types.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<bits/stdc++.h>
using namespace std;
#include<sys/epoll.h>
#include<unistd.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<netinet/in.h>
#define MAX_CLIENTS 10
using namespace std;
namespace ser{
class server{
public:
static int Socket(){
int sd=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if(sd<0)
exit(1);
else
return sd;
}
static bool Bind(int sd,uint32_t port){
struct sockaddr_in laddr;
laddr.sin_family=AF_INET;
laddr.sin_port=htons(port);
//laddr.sin_addr.s_addr=INADDR_ANY;
inet_pton(AF_INET,"0.0.0.0",&laddr.sin_addr);
if(bind(sd,(const sockaddr*)&laddr,(socklen_t)sizeof laddr)<0)
exit(1);
return true;
}
static bool Listen(int sd){
if(listen(sd,6)<0)
exit(1);
return true;
}
};
}
e_s.h
#include"s.h"
namespace e_s{
class epoll_s{
private:
int l_sd;
int port;
public:
epoll_s(int _port):port(_port){}
void Init(){
l_sd=ser::server::Socket();
if(ser::server::Bind(l_sd,port)<0){
exit(1);
}
if(ser::server::Listen(l_sd)<0){
exit(1);
}
}
//use epoll 主要代码
void Run(){
cout<<"Runing..."<<endl;
struct epoll_event ev,evs[MAX_CLIENTS];//进行epoll_event的变量的初始化和其数组的初始化,数组只是用来隐含地返回发生的时间的描述符 只有在epoll_wait时才会用到数组 epoll_wait(int epfd,struct epoll_event* evs,int max_evs,int time_out)
ev.data.fd=l_sd;//进行epoll_event变量的赋值 监听的对象,监听对象的监听的事件 l_sd EPOLLIN 可读事件
ev.events=EPOLLIN;
struct epoll_event mid_ev;//临时变量epoll_evennt其实也可以不需要 因为用ev就行了 目的就是添加到epoll描述符(epoll_create 返回值)中
int e_fd=epoll_create(2);//epoll描述符
epoll_ctl(e_fd,EPOLL_CTL_ADD,l_sd,&ev); //增加监听的对象
while(true){
cout<<"Ready for waiting!"<<endl;
int num=epoll_wait(e_fd,evs,MAX_CLIENTS,-1);//阻塞等待
cout<<"wait is over."<<endl;
//cout<<"num is "<<num<<endl;
for(int i=0;i<num;++i){
if(evs[i].data.fd==l_sd){//是监听的对象改变了 说明有新的连接
struct sockaddr_in raddr;
socklen_t len;
int new_sd=accept(l_sd,(struct sockaddr*)&raddr,&len);
char str[1024];
inet_ntop(AF_INET,&raddr.sin_addr,str,sizeof str);
cout<<"connected by"<<str<<" port:"<<ntohs(raddr.sin_port)<<endl;
mid_ev.data.fd=new_sd;//将连接的描述符进行监视对象的初始化
mid_ev.events=EPOLLIN;
epoll_ctl(e_fd,EPOLL_CTL_ADD,new_sd,&mid_ev);//将连接的描述符进行添加到监视队列中
}
else
{
//连接对象发生改变 说明对端发来了消息
char buf[1024];
int n=read(evs[i].data.fd,buf,sizeof buf);
buf[n]='\0';
cout<<"Receive : "<<buf<<endl;
}
}
}
}
};
}
e_s.cpp
#include"e_s.h"
int main(int argc,char** argv){
e_s::epoll_s* s=new e_s::epoll_s(atoi(argv[1]));
s->Init();
s->Run();
return 0;
}