ubuntu12.04中epoll设为“边缘触发”的疑惑

coderchenjingui 2013-05-31 03:25:52
学习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 daaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaggggggggggggggggggggggggg
5 gggggggggggggggggggggggggggggggggggggggggggggggggrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr
5 rrrrrrrrr
...全文
179 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
heartlesstoanyone 2013-06-06
  • 打赏
  • 举报
回复
边缘触发,只会通知你一次,除非状态发生了改变 或通过MOD强制触发,前提是,其实可读/可写
heartlesstoanyone 2013-06-03
  • 打赏
  • 举报
回复
边缘触发,对recv,一定要recv直到遇到EAGAIN为止。
xengine-qyt 2013-06-03
  • 打赏
  • 举报
回复
虽然不知道你在说什么,但是感觉很NB。 你提供的缓冲区100个字节 数据到达事件肯定会被触发多次啊,不然你怎么处理的完数据,不然一个事件触发一次,无论ET或者LT
coderchenjingui 2013-06-03
  • 打赏
  • 举报
回复
引用 4 楼 heartlesstoanyone 的回复:
边缘触发,对recv,一定要recv直到遇到EAGAIN为止。
恩,我知道了。 但是我不理解的还是老地方。 为什么我设置为边缘触发,而又只读取部分的时候,下载调用epoll_wait的时候,还会通知我呢? 这样与水平触发没有区别了把。
coderchenjingui 2013-05-31
  • 打赏
  • 举报
回复
引用 1 楼 aaadddzxc 的回复:
虽然不知道你在说什么。。。。但是没啥问题@!
我刚才没有说清楚。 我的问题和这个兄弟的们体一模一样。 http://bbs.csdn.net/topics/390352496
xengine-qyt 2013-05-31
  • 打赏
  • 举报
回复
虽然不知道你在说什么。。。。但是没啥问题@!

23,121

社区成员

发帖
与我相关
我的任务
社区描述
Linux/Unix社区 应用程序开发区
社区管理员
  • 应用程序开发区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧