基础原理理解请参考这篇:
IO - 同步,异步,阻塞,非阻塞 (亡羊补牢篇)
select主要解决的问题:(详细请参考:select用法&原理详解(源码剖析))
select/epoll区别:如果这篇文章说不清epoll的本质,那就过来掐死我吧!
服务端:
//服务端 gcc server_epoll.c -o server_epoll
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define true 1
#define false 0
#define MAX_EVENT_NUMBER 1024
#define BUFFER_SIZE 10
/*将文件描述符设置为非阻塞*/
int setnonblocking(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;
}
/*将文件描述符fd上的EPOLLIN注册到epollfd指示的epoll内核事件表中。 参数enable_et 指定是否对fd采用ET模式*/
void addfd(int epollfd, int fd, int enable_et)
{
struct epoll_event event;
event.data.fd = fd;
event.events = EPOLLIN;
if(enable_et){
event.events |= EPOLLET;
}
epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &event );
setnonblocking(fd);
}
/*LT 模式的工作原理*/
void lt(struct epoll_event *events, int number, int epollfd, int listenfd)
{
char buf[BUFFER_SIZE];
int i = 0;
for(i= 0;i= 0);
ret = bind(listenfd, (struct sockaddr *)&address, sizeof(address));
assert(ret != -1);
ret = listen(listenfd, 5);//监听队列最多容纳5个
assert(ret != -1);
struct epoll_event events[MAX_EVENT_NUMBER];
int epollfd = epoll_create(5);
assert(epollfd != -1);
addfd(epollfd, listenfd, true);
while(1){
int ret = epoll_wait(epollfd, events, MAX_EVENT_NUMBER, -1);
if(ret<0){
printf("epoll failure\n");
break;
}
lt(events, ret, epollfd, listenfd);
//et(events, ret, epollfd, listenfd);
}
close(listenfd);
return 0;
}
客户端:
//客户端 gcc client.c -o client
#include
#include
#include
#include
#include
#include
#include
#include
int main()
{
int client_sockfd;
int len;
struct sockaddr_in address;//服务器端网络地址结构体
int result;
char ch = 'A';
client_sockfd = socket(AF_INET, SOCK_STREAM, 0);//建立客户端socket
address.sin_family = AF_INET;
address.sin_addr.s_addr = inet_addr("127.0.0.1");
address.sin_port = htons(8888);
len = sizeof(address);
result = connect(client_sockfd, (struct sockaddr *)&address, len);
if(result == -1)
{
perror("oops: client2");
exit(1);
}
printf("client_sockfd = %d\n", client_sockfd);
//第一次读写
write(client_sockfd, &ch, 1);
printf("first client write over!\n");
read(client_sockfd, &ch, 1);
printf("first client read over!\n");
printf("the first time: char from server = %c sleep 5s\n", ch);
sleep(5);
//第二次读写
write(client_sockfd, &ch, 1);
printf("second client write over!\n");
read(client_sockfd, &ch, 1);
printf("second client read over!\n");
printf("the second time: char from server = %c\n", ch);
close(client_sockfd);
return 0;
}
执行结果: