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;
}