多路复用I/O模型epoll() 模型 代码实现
epoll模型
int epoll_create(int maxevent) //创建一个epoll的句柄 然后maxevent表示监听的数目的大小
int epoll_ctl(int epollfd,int op,int fd,struct epoll_event *event) //epoll的事件注册函数
/*
epollfd 为epoll_create()的返回值
op 表示为相应的操作
fd 为套接字
*event 表示监听什么事件
*/
OP 有
EPOLL_CTL_ADD:注册新的fd到epfd中;
EPOLL_CTL_MOD:修改已经注册的fd的监听事件;
EPOLL_CTL_DEL:从epfd中删除一个fd;
int epoll_wait(int epollfd,struct epoll_event *event,int maxevents,int timeout);
/*
epollfd epoll_create的返回值
*event 从内核得到时间的集合
maxevents 告诉内核event多大 不能大于epoll_create()中的maxevent
timeout 表示等待的时间-1表示阻塞 0表示立即返回
*/
epoll_event结构体
struct epoll_event {
__uint32_t events; /* Epoll events */
epoll_data_t data; /* User data variable */
};
typedef union epoll_data
{
void *ptr;
int fd;
uint32_t u32;
uint64_t u64;
} epoll_data_t;
其中epoll_event 结构体中的events参数的值是宏定义:
EPOLLIN :表示对应的文件描述符可以读(包括对端SOCKET正常关闭);
EPOLLOUT:表示对应的文件描述符可以写;
EPOLLPRI:表示对应的文件描述符有紧急的数据可读(这里应该表示有带外数据到来);
EPOLLERR:表示对应的文件描述符发生错误;
EPOLLHUP:表示对应的文件描述符被挂断;
EPOLLET: 将EPOLL设为边缘触发(Edge Triggered)模式,这是相对于水平触发(Level Triggered)来说的。
EPOLLONESHOT:只监听一次事件,当监听完这次事件之后,如果还需要继续监听这个socket的话,需要再次把这个socket加入到EPOLL队列里
data.h
#ifndef DATA_H
#define DATA_H
#include <string.h>
#include <stdio.h>
#include <sys/epoll.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <errno.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <assert.h>
#include <sys/types.h> #define IP "127.0.0.1"
#define PORT 4578
#define maxn 1100
#define MAXLINE 100
#define BACKLOG 5
#define EPOLLEVENTS 1120
#define _EVENTS 100
#endif
server.c
#include "data.h"
static void epoll_accept(int sockfd);
static void submit_to_check(int epollfd,struct epoll_event *events,int num,int sockfd,char *buf);
static void submit_to_read(int epollfd,int conn,char *buf);
static void submit_to_write(int epollfd,int conn,char *buf);
static void submit_to_accept(int epollfd,int conn);
static void change_event(int epollfd,int conn,int ser_event);
static void change_delete(int epollfd,int conn,int ser_event);
static void add_event(int epollfd,int sockfd,int ser_event); static int init()
{
int sockfd;
struct sockaddr_in server_in;
if((sockfd = socket(AF_INET,SOCK_STREAM,)) == -)
{
fprintf(stderr,"socket fail,error %s",strerror(errno));
return -;
}
bzero(&server_in,sizeof(server_in));
server_in.sin_family = AF_INET;
server_in.sin_port = htons(PORT);
inet_pton(AF_INET,IP,&server_in.sin_addr);
if(bind(sockfd,(struct sockaddr*)&server_in,sizeof(server_in)) == -)
{
fprintf(stderr,"bind fail,error %s",strerror(errno));
return -;
}
listen(sockfd,BACKLOG);
return sockfd;
} static void epoll_accept(int sockfd)
{
int epollfd;
char buf[maxn];
memset(buf,,sizeof(buf));
struct epoll_event events[_EVENTS];
epollfd = epoll_create(EPOLLEVENTS);
int ret;
add_event(epollfd,sockfd,EPOLLIN);
for(;;)
{
ret = epoll_wait(epollfd,events,_EVENTS,-);
submit_to_check(epollfd,events,ret,sockfd,buf);
}
close(epollfd);
}
static void submit_to_check(int epollfd,struct epoll_event *events,int num,int sockfd,char *buf)
{
int i;
int fd;
for(i=;i<num;i++)
{
fd = events[i].data.fd;
if((fd == sockfd) && (events[i].events&EPOLLIN))
{
submit_to_accept(epollfd,sockfd);
}
else if(events[i].events & EPOLLIN)
{
submit_to_read(epollfd,fd,buf);
}
else if(events[i].events & EPOLLOUT)
{
submit_to_write(epollfd,fd,buf);
}
}
}
static void submit_to_read(int epollfd,int conn,char *buf)
{
int n;
n = read(conn,buf,maxn);
if(n == )
{
fprintf(stderr,"client close!\n");
close(conn);
change_delete(epollfd,conn,EPOLLIN);
}
else if(n == -)
{
fprintf(stderr,"read error\n");
close(conn);
change_delete(epollfd,conn,EPOLLIN);
}
else
{
fprintf(stderr,"read message is %s\n",buf);
change_event(epollfd,conn,EPOLLOUT);
}
}
static void submit_to_write(int epollfd,int conn,char *buf)
{
int n;
n = write(conn,buf,strlen(buf));
if(n == -)
{
printf("server closed!\n");
close(conn);
change_delete(epollfd,conn,EPOLLOUT);
}
else
{
change_event(epollfd,conn,EPOLLIN);
}
memset(buf,'\0',sizeof(buf));
}
static void submit_to_accept(int epollfd,int conn)
{
struct sockaddr_in server_in;
bzero(&server_in,sizeof(server_in));
socklen_t socklen;
int afd;
socklen = ;
if((afd = accept(conn,(struct sockaddr*)&server_in,&socklen)) == -)
{
fprintf(stderr,"accept fail,error %s\n",strerror(errno));
return;
}
else
{
printf("accept a new client:%s :%d\n",inet_ntoa(server_in.sin_addr),server_in.sin_port);
add_event(epollfd,afd,EPOLLIN);
}
}
static void change_event(int epollfd,int conn,int ser_event)
{
struct epoll_event eventfd;
eventfd.data.fd = conn;
eventfd.events = ser_event;
epoll_ctl(epollfd,EPOLL_CTL_MOD,conn,&eventfd);
}
static void change_delete(int epollfd,int conn,int ser_event)
{
struct epoll_event eventfd;
eventfd.data.fd = conn;
eventfd.events = ser_event;
epoll_ctl(epollfd,EPOLL_CTL_DEL,conn,&eventfd);
}
static void add_event(int epollfd,int sockfd,int ser_event)
{
struct epoll_event eventfd;
eventfd.data.fd = sockfd;
eventfd.events = ser_event;
epoll_ctl(epollfd,EPOLL_CTL_ADD,sockfd,&eventfd);
} int main()
{ int sockfd;
sockfd = init();
epoll_accept(sockfd);
close(sockfd);
return ;
}
client.c
#include "data.h" static void connect_server(int sockfd);
static void submit_to_check(int epollfd,struct epoll_event *events,int num,int sockfd,char *buf);
static void submit_to_read(int epollfd,int fd,int sockfd,char *buf);
static void submit_to_write(int epollfd,int fd,int sockfd,char *buf);
static void change_event(int epollfd,int sockfd,int ser_event);
static void change_delete(int epollfd,int sockfd,int ser_event);
static void add_event(int epollfd,int sockfd,int ser_event); static int init()
{
struct sockaddr_in client_in;
int sockfd;
if((sockfd = socket(AF_INET,SOCK_STREAM,)) == -)
{
fprintf(stderr,"socket fail,error %s\n",strerror(errno));
return -;
}
bzero(&client_in,sizeof(client_in));
client_in.sin_family = AF_INET;
client_in.sin_port = htons(PORT);
inet_pton(AF_INET,IP,&client_in.sin_addr);
connect(sockfd,(struct sockaddr*)&client_in,sizeof(client_in)) ;
return sockfd;
}
static void connect_server(int sockfd)
{
int epollfd;
struct epoll_event events[_EVENTS];
epollfd = epoll_create(EPOLLEVENTS);
char buf[maxn];
int conn;
memset(buf,'\0',sizeof(buf));
add_event(epollfd,STDIN_FILENO,EPOLLIN);
for(;;)
{
fprintf(stderr,"Please input message!\n");
conn = epoll_wait(epollfd,events,_EVENTS,-);
submit_to_check(epollfd,events,conn,sockfd,buf);
}
close(epollfd);
}
static void submit_to_check(int epollfd,struct epoll_event *events,int num,int sockfd,char *buf)
{
int i;
int fd;
for(i=;i<num;i++)
{
fd = events[i].data.fd;
if(events[i].events & EPOLLIN)
{
submit_to_read(epollfd,fd,sockfd,buf);
}
else if(events[i].events & EPOLLOUT)
{
submit_to_write(epollfd,fd,sockfd,buf);
}
}
}
static void submit_to_read(int epollfd,int fd,int sockfd,char *buf)
{
memset(buf,'\0',sizeof(buf));
int n;
n = read(fd,buf,maxn);
if(n == )
{
fprintf(stderr,"server close.\n");
close(fd);
}
else if(n == -)
{
perror("read error:");
close(fd);
}
else
{
if(fd == STDIN_FILENO)
add_event(epollfd,sockfd,EPOLLOUT);
else
{
change_delete(epollfd,sockfd,EPOLLIN);
add_event(epollfd,STDOUT_FILENO,EPOLLOUT);
}
}
}
static void submit_to_write(int epollfd,int fd,int sockfd,char *buf)
{
int n;
n = write(fd,buf,strlen(buf));
if(n == -)
{
perror("write error:");
close(fd);
}
else
{
if(fd == STDOUT_FILENO)
{
change_delete(epollfd,fd,EPOLLOUT);
}
else
{
change_event(epollfd,fd,EPOLLIN);
}
}
memset(buf,,sizeof(buf));
}
static void change_event(int epollfd,int sockfd,int ser_event)
{
struct epoll_event eventfd;
eventfd.data.fd = sockfd;
eventfd.events = ser_event;
epoll_ctl(epollfd,EPOLL_CTL_MOD,sockfd,&eventfd);
}
static void change_delete(int epollfd,int sockfd,int ser_event)
{
struct epoll_event eventfd;
eventfd.data.fd = sockfd;
eventfd.events = ser_event;
epoll_ctl(epollfd,EPOLL_CTL_DEL,sockfd,&eventfd);
} static void add_event(int epollfd,int sockfd,int ser_event)
{
struct epoll_event eventfd;
eventfd.data.fd = sockfd;
eventfd.events = ser_event;
epoll_ctl(epollfd,EPOLL_CTL_ADD,sockfd,&eventfd);
}
int main()
{
int sockfd = init();
connect_server(sockfd);
close(sockfd);
return ;
}
多路复用I/O模型epoll() 模型 代码实现的更多相关文章
- nginx中的epoll模型
要了解epoll模型,就要一个一个知识点由浅至深地去探索. 1.IO复用技术 IO流请求操作系统内核,有串行处理和并行处理两种概念. 串行处理是前面一个操作处理地时候,后面的所有操作都需要等待.因此, ...
- 多路复用I/O模型poll() 模型 代码实现
多路复用I/O模型poll() 模型 代码实现 poll()机制和select()机制是相似的,都是对多个描述符进行轮询的方式. 不同的是poll()没有描述符数目的限制. 是通过struct pol ...
- Epoll模型详解
Linux 2.6内核中提高网络I/O性能的新方法-epoll I/O多路复用技术在比较多的TCP网络服务器中有使用,即比较多的用到select函数. 1.为什么select落后 首先,在Lin ...
- 【转】select和epoll模型的差异
http://www.cppblog.com/converse/archive/2008/10/12/63836.html epoll为什么这么快 epoll是多路复用IO(I/O Multiplex ...
- linux epoll模型
原文:http://yjtjh.blog.51cto.com/1060831/294119 Linux I/O多路复用技术在比较多的TCP网络服务器中有使用,即比较多的用到select函数.Linux ...
- (OK) Linux epoll模型—socket epoll server client chat
http://www.cnblogs.com/venow/archive/2012/11/30/2790031.html http://blog.csdn.net/denkensk/article/d ...
- 基于EPOLL模型的局域网聊天室和Echo服务器
一.EPOLL的优点 在Linux中,select/poll/epoll是I/O多路复用的三种方式,epoll是Linux系统上独有的高效率I/O多路复用方式,区别于select/poll.先说sel ...
- 并发编程-epoll模型的探索与实践
前言 我们知道nginx的效率非常高,能处理上万级的并发,其之所以高效离不开epoll的支持, epoll是什么呢?,epoll是IO模型中的一种,属于多路复用IO模型; 到这里你应该想到了,sele ...
- go标准库I/O模型:epoll+多协程
本文为linux环境下的总结,其他操作系统本质差别不大.本地文件I/O和网络I/O逻辑类似. epoll+多线程的模型 epoll+多线程模型和epoll 单进程区别.优点 对比于redis这 ...
随机推荐
- 洛谷 P2730 魔板 Magic Squares 解题报告
P2730 魔板 Magic Squares 题目背景 在成功地发明了魔方之后,鲁比克先生发明了它的二维版本,称作魔板.这是一张有8个大小相同的格子的魔板: 1 2 3 4 8 7 6 5 题目描述 ...
- Codeforces 864E Fire(背包DP)
背包DP,决策的时候记一下 jc[i][j]=1 表示第i个物品容量为j的时候要选,输出方案的时候倒推就好了 #include<iostream> #include<cstdlib& ...
- 你会喜欢的前端^o^!
前端那些事儿 网页设计常用色彩搭配表 很漂亮的alert弹出框 一个让你想到即可做到的web弹窗/层解决方案 基于HTML5的在绘图特效平台(酷炫)
- 爬虫实例——爬取煎蛋网OOXX频道(反反爬虫——伪装成浏览器)
煎蛋网在反爬虫方面做了不少工作,无法通过正常的方式爬取,比如用下面这段代码爬取无法得到我们想要的源代码. import requests url = 'http://jandan.net/ooxx' ...
- bzoj 4695 最假女选手 吉利线段树
最假女选手 Time Limit: 50 Sec Memory Limit: 128 MBSubmit: 480 Solved: 118[Submit][Status][Discuss] Desc ...
- 求前n项正整数的倒数和
求前n项正整数的倒数和 前n项正整数的和是一个发散的序列,学过高等数学的这个都知道.所以它没有一个精确的公式,但是近似的公式是有的: 1 + 1/2 + 1/3 + …… + 1/n ≍ ln n + ...
- 51Nod 1049最大子段和 | 模板
Input示例 6 -2 11 -4 13 -5 -2 Output示例 20 1.最大子段和模板 #include "bits/stdc++.h" using namespace ...
- bigDecimal学习
1.引言 float和double类型的主要设计目标是为了科学计算和工程计算.他们执行二进制浮点运算,这是为了在广域数值范围上提供较为精确的快速近似计算而精心设计的.然而,它们没有提供完全精确的结果, ...
- Codeforces Round #411 (Div. 2) A-F
比赛时候切了A-E,fst了A Standings第一页只有三个人挂了A题,而我就是其中之一,真™开心啊蛤蛤蛤 A. Fake NP time limit per test 1 second memo ...
- 汕头市队赛 SRM19 字符题
从天上掉下来了个这样的问题: 有一个字符串 从中选出两个子串 A,B,求 A+B可以构成的不同串的个数. 还想知道,这么多个串中字典序最大的那一个. 某人捡到了这个问题,并把它扔给了你. [输入] 一 ...