for ( ; ; ) {
//等待epoll事件的发生
nfds=epoll_wait(epfd,events,20,500);
//处理所发生的所有事件
for(i=0;i<nfds;++i)
{
if(events[i].data.fd==listenfd)
{
connfd = accept(listenfd,(sockaddr *)&clientaddr,
&clilen);
if(connfd<0){
perror("connfd<0");
exit(1);
}
setnonblocking(connfd);
char *str = inet_ntoa(clientaddr.sin_addr);
std::cout<<"connect from "<_u115 ?tr<<std::endl;
//设置用于读操作的文件描述符
ev.data.fd=connfd;
//设置用于注测的读操作事件
ev.events=EPOLLIN|EPOLLET;
//注册ev
epoll_ctl(epfd,EPOLL_CTL_ADD,connfd,&ev);
}
else if(events[i].events&EPOLLIN)
{
if ( (sockfd = events[i].data.fd) < 0) continue;
if ( (n = read(sockfd, line, MAXLINE)) < 0) {
if (errno == ECONNRESET) {
close(sockfd);
events[i].data.fd = -1;
} else
std::cout<<"readline error"<<std::endl;
} else if (n == 0) {
close(sockfd);
events[i].data.fd = -1;
}
//设置用于写操作的文件描述符
ev.data.fd=sockfd;
//设置用于注测的写操作事件
ev.events=EPOLLOUT|EPOLLET;
//修改sockfd上要处理的事件为EPOLLOUT
epoll_ctl(epfd,EPOLL_CTL_MOD,sockfd,&ev);
}
else if(events[i].events&EPOLLOUT)
{
sockfd = events[i].data.fd;
write(sockfd, line, n);
//设置用于读操作的文件描述符
ev.data.fd=sockfd;
//设置用于注测的读操作事件
ev.events=EPOLLIN|EPOLLET;
//修改sockfd上要处理的事件为EPOLIN
epoll_ctl(epfd,EPOLL_CTL_MOD,sockfd,&ev);
}
}
}
为发现他的作者在添加每个event的时候都是用ev.events=EPOLLIN|EPOLLET;
然后在发现一个fd可读时ev.events=EPOLLOUT|EPOLLET;
在一个fd可写时ev.events=EPOLLIN|EPOLLET;
我不懂他这么做有什么考虑
我的想法很简单:
在添每个fd时都ev.events=EPOLLIN|EPOLLOUT|EPOLLET;
然后该读就读,该写就写,不再反复调用epoll_ctl来更改
我这么做可行吗?
我如果这么写echo server,是否正确?
...
for(;;){
nfds=epoll_wait(epfd,events,20,500);
for(i=0;i<nfds;i++){
if(events[i].data.fd==listenfd){
...
ev.events=EPOLLIN|EPOLLOUT|EPOLLET;
...
}else if((events[i].events&EPOLLIN)){
...
if ( (n = read(sockfd, line, MAXLINE)) < 0) {
...
}
write(sockfd,line, n);
}
}
也就是说在EPOLLIN发生时,接收到数据后,立刻发回原sockfd,这样不就实现了echo了吗?
我实验好像不成功