日期:2014-05-16  浏览次数:20776 次

ubuntu12.04中epoll设为“边缘触发”的疑惑
学习epoll模型的时候,我的服务器端设置为边缘触发,然后每次epoll_wait之后只接收100字节的内容。
客户端连接server之后,发送大于100个字节的内容,按理说服务器监听的这个套接口设为边缘触发之后,应该只会读取一次的,但是实际情况确实把客户端发的东西多次读取出来了。
也就时,我设置为了边缘触发,但是服务器端只读取客户端发来的部分内容,再次epoll_wait还是返回了这个套接字。
下面的server的代码

#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <sys/epoll.h>

#define MAX_FD 10
int getPortFromParam(int argc, char *argv[]);
int main(int argc, char *argv[])
{
int port = getPortFromParam(argc, argv);
int listenfd = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in socksrv;
bzero(&socksrv, sizeof(socksrv));
socksrv.sin_addr.s_addr = htonl(INADDR_ANY);
socksrv.sin_family = AF_INET;
socksrv.sin_port = htons(port);
int result = bind(listenfd, (struct sockaddr*)&socksrv, sizeof(socksrv));
if(result == -1) {
perror("bind error!");
exit(1);
}
result = listen(listenfd, 10);
if(result == -1) {
perror("listen error1");
exit(1);
}

struct epoll_event ev, events[MAX_FD];
int kdpfd = epoll_create(MAX_FD);
ev.events = EPOLLIN;
ev.data.fd = listenfd;
epoll_ctl(kdpfd, EPOLL_CTL_ADD, listenfd, &ev);
while(1) {
int nfds = epoll_wait(kdpfd, events,MAX_FD, -1);
if(nfds == -1) {
perror("eait error.");
printf("%d \n", errno);
exit(1);
}
int i;
for(i = 0; i < nfds; i++) {
if(events[i].data.fd == listenfd) {
int clifd = accept(listenfd, NULL, NULL);
if(clifd < 0) 
continue;
printf("%d connected!\n", clifd);
int flags = fcntl(clifd, F_GETFL, 0);
fcntl(clifd, F_SETFL, flags | O_NONBLOCK);
ev.events = EPOLLIN | EPOLLET;
ev.data.fd = clifd;
epoll_ctl(kdpfd, EPOLL_CTL_ADD, clifd, &ev);
} else {
char buf[100] = {0};
int nread = read(events[i].data.fd, buf, sizeof(buf));
if(nread == 0) { //EOF
printf("%d closed!\n", events[i].data.fd);
close(events[i].data.fd);
epoll_ctl(kdpfd, EPOLL_CTL_DEL, events[i].data.fd, NULL);
} else if(nread > 0) {
buf[ nread -1 ] = 0;
printf("%d %s\n", events[i].data.fd, buf);
}
}
}
}
return 0;
}


int getPortFromParam(int argc, char *argv[])
{
if(argc !=  2) {
printf("%s <port>\n", argv[0]);
exit(1);
}
return atoi(argv[1]);
}


然后,客户端连接过来,发送大于100个字节的内容,然后服务器这边的执行结果时这样的:
root@chenjingui-pc:/home/chenjingui/workspace/unp/epoll# ./srv 5757
5 connected!
5 asdfasdfffffffadddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
5