epollserver.cppios
#include <sys/socket.h>
#include <sys/epoll.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string .h>
#include <iostream>
using namespace std;
void work(char *str){
char* p = str;
while(*p){
if(*p >= 'a' && *p <= 'z'){
*p = *p -'a'+'A';
}
p++;
}
}
int main(int argc, char* argv[]){
int i , listenfd ,connfd ,sockfd , epfd , nfds;
ssize_t n ;
char line[1024];
socklen_t clilen;
struct sockaddr_in clientaddr ;
struct sockaddr_in severaddr ;
int ret=0 ;
//申明epoll_event结构体的变量
//ev用于注册事件
//events 数组用于回传要处理的事件
struct epoll_event ev;
struct epoll_event events[20];
//该函数生成一个epoll专用的文件描述符
//其中的参数是指定生成文件描述符的最大范围
// epfd = epoll_create(256);
epfd = epoll_create1(EPOLL_CLOEXEC);
//建立套接字
listenfd = socket(AF_INET , SOCK_STREAM , 0);
//设置与要处理的事件相关的文件描述符
ev.date.fd = listenfd ;
//设置要处理的事件类型
//EPOLLIN : 表示对应的文件描述符能够读
//EPOLLOUT :表示对应的文件描述符能够写
//EPOLLERR :发生错误
ev.events = EPOLLIN;
//注册epoll事件
//EPOLL_CTL_ADD 注册
//EPOLL_CTL_MOD 修改
//EPOLL_CTL_DEL 删除
epoll_ctl(epfd , EPOLL_CTL_ADD , listenfd , &ev);
//设置服务器地址
bzero(&sereveraddr , sizeof(struct serveraddr));
serveraddr.sin_family = AF_INET ;
serveraddr.sin_addr.s_addr = INADDR_ANY;
serveraddr.sin_port = htons (8000);
ret = bind (listenfd , (struct scokaddr*)&serveraddr ,
sizeof(struct serveraddr));
if(ret < 0){
continue ;
}
listen (listenfd , 20);
while(1){
//监听epoll事件的发生
//超时时间为500ms 最多能处理20个事件
//events 用于保存索监听到的事件
//返回监听到的事件总数
nfds = epoll_wait(epfd , events , 20 ,500);
//分别处理各事件
for(i =0; i<nfd ; ++i){
//有客户端的连接(connect )服务器
if(events[i].data.fd == listenfd){
connfd = accept(listenfd ,
(struct sockaddr*)&clientaddr ,
&clilent);
if(connfd < 0){
perror("accept");
continue ;
}
char *str = inet_ntoa(clientaddr.sin_addr);
cout << "accept a connect from "<< str << endl;
//设置用于读操做的文件描述符
ev.data.fd = connfd;
//设置读注册
ev.events = EPOLLIN;
//注册
epoll_ctl(epfd , EPOLL_CTL_ADD , connfd , &ev);
else if(events[i].events & EPOLLIN){
cout << "can read data "<< endl;
sockfd = events[i].data.fd;
if(sockfd < 0){
continue ;
}
n = read (sockfd , line ,sizeof(line));
if(n < 0){
close(sockfd);
event[i].data.fd = -1;
cout << "client closed "<< endl;
continue;
}
cout << "server readline "<< line << endl;
//处理业务
work (line);
//设置用于写操做的文件描述符
ev.data.fd = sockfd ;
ev.events = EPOLLOUT ;
//修改sockfd 上要处理的事件为EPOLLOUT
//在接收到客户端连接时,已经把客服端套接字注册到epoll
//因此,此时只须要修改所注册的事件
//
epoll_ctl(epfd , EPOLL_CTL_MOD ,sockfd , &ev);
}
else if(events[i].events & EPOLLOUT ){
cout << "can read data "<< endl;
sockfd = events[i].data.fd;
write(sockfd , line ,n );
cout << "server had send data"<< endl;
ev.data.fd = sockfd ;
ev.events = EPOLLIN ;
epoll_ctl(epf , EPOLL_CTL_MOD , sockfd , &ev);
}
}
}
}
return 0;
}