LT(水平模式):事件如果没有被处理完会多次触发
ET(边沿模式):事件只会触发一次
服务器代码:
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<assert.h>
#include<stdio.h>
#include<unistd.h>
#include<errno.h>
#include<string.h>
#include<fcntl.h>
#include<stdlib.h>
#include<sys/epoll.h>
#include<pthread.h>
#define MAX_EVENT_NUMBER 1024
#define BUFFER_SIZE 10
int setnonblock(int fd){
int old_option = fcntl(fd, F_GETFL);
int new_option = old_option | O_NONBLOCK;
fcntl(fd, F_SETFL, new_option);
return old_option;
}
void addfd(int epollfd, int fd, bool enable_et){
epoll_event event;
event.data.fd = fd;
event.events = EPOLLIN;
if(enable_et){
event.events |= EPOLLET;
}
epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &event);
setnonblock(fd);
}
void lt(epoll_event* events, int number, int epollfd, int listenfd){
char buf[BUFFER_SIZE];
for(int i = 0; i < number; ++i){
int sockfd = events[i].data.fd;
if(sockfd == listenfd){
struct sockaddr_in client_addr;
socklen_t client_addrlen;
int connfd = accept(listenfd, (struct sockaddr*)&client_addr, &client_addrlen);
addfd(epollfd, connfd, false);
}else if(events[i].events & EPOLLIN){
printf("triger once\n");
memset(buf, '\0', BUFFER_SIZE);
int ret = recv(sockfd, buf, BUFFER_SIZE, 0);
if(ret <= 0){
close(sockfd);
continue;
}
printf("recieve %d bytes data:%s\n", ret, buf);
}else{
printf("something else happened\n");
}
}
}
void et(epoll_event* events, int number, int epollfd, int listenfd){
char buf[BUFFER_SIZE];
for(int i = 0; i < number; ++i){
int sockfd = events[i].data.fd;
if(sockfd == listenfd){
struct sockaddr_in client_addr;
socklen_t client_addrlen;
int connfd = accept(listenfd, (struct sockaddr*)&client_addr, &client_addrlen);
addfd(epollfd, connfd, true);
}else if(events[i].events & EPOLLIN){
printf("triger once\n");
while(1){
memset(buf, '\0', BUFFER_SIZE);
int ret = recv(sockfd, buf, BUFFER_SIZE, 0);
if(ret < 0){
if(errno == EAGAIN || errno == EWOULDBLOCK){
printf("read later");
break;
}
close(sockfd);
break;
}else if(ret == 0){
printf("read finish \n");
close(sockfd);
}else{
printf("recieve %d bytes data:%s\n", ret, buf);
}
}
}else{
printf("something else happened\n");
}
}
}
int main(int argc, char* argv[]){
if(argc < 3){
printf("ip & port \n");
return 0;
}
char* ip = argv[1];
int port = atoi(argv[2]);
int listenfd = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in addr;
bzero(&addr, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
inet_pton(AF_INET, ip, &addr.sin_addr);
int ret = bind(listenfd, (struct sockaddr*)&addr, sizeof(addr));
ret = listen(listenfd, 5);
int epollfd = epoll_create(5);
epoll_event events[MAX_EVENT_NUMBER];
addfd(epollfd, listenfd, false);
while(1){
ret = epoll_wait(epollfd, events, MAX_EVENT_NUMBER, -1);
if(ret < 0){
printf("epoll failure \n");
break;
}
lt(events, ret, epollfd, listenfd);
//et();
}
close(epollfd);
close(listenfd);
return 0;
}
客户端代码:
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<assert.h>
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<errno.h>
#include<string.h>
#define BUFFER_SIZE 1024
int main(int argc, char* argv[]){
if(argc <= 2){
printf("ip and port and size!!!\n");
return 0;
}
char* ip = argv[1];
int port = atoi(argv[2]);
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in serveraddr;
bzero(&serveraddr, sizeof(serveraddr));
serveraddr.sin_family = AF_INET;
serveraddr.sin_port = htons(port);
inet_pton(AF_INET, ip, &serveraddr.sin_addr);
if((connect(sockfd, (struct sockaddr*)&serveraddr, sizeof(serveraddr))) < 0){
printf("connect failure \n");
}else{
char data[] = "aaaaaaaaaabbbbb";
send(sockfd, data, strlen(data), 0);
//send(sockfd, ndata, strlen(ndata), 0);
printf("send finished!\n");
}
close(sockfd);
return 0;
}
LT运行结果:
ET运行结果:
可以看到,ET只触发了一次