安徽网淮南频道,seo搜索优化公司,网站首页导航栏怎么做,游戏网站风格1.epoll工作模式
水平触发 LT
边沿触发 ET 因为设置为水平触发,只要缓存区有数据epoll_wait就会被触发,epoll_wait是一个系统调用,尽量少调用
所以尽量使用边沿触发,边沿出触发数据来一次只触发一次,这个时候要求一次性将数据读完,所以while循环读,读到最后read默认带阻塞…1.epoll工作模式
水平触发 LT
边沿触发 ET 因为设置为水平触发,只要缓存区有数据epoll_wait就会被触发,epoll_wait是一个系统调用,尽量少调用
所以尽量使用边沿触发,边沿出触发数据来一次只触发一次,这个时候要求一次性将数据读完,所以while循环读,读到最后read默认带阻塞,不能让read阻塞,因为不能再去监听,
设置cfd为非阻塞,read读到最后一次返回值为-1.判断errno的值为EAGAIN,代表数据读干净
工作中 边沿触发 非阻塞 高速模式
创建lfd,监听创建树epfd写epoll_event事件事件是结构体ev.data.fdev.events(EPOLLIN 或者EPOLLOUT)epoll_ctl对文件描述符对上树EPOLL_CTL_ADD或者下树EPOLL_CTL_DEVepoll_wait监听返回值是变化的数量先判断lfd变化的操作是创建新的cfd然后再将其上树注意设置非阻塞再判断cfd变化的操作要设置一个标志位一次性读完数据别忘记关闭文件描述符和下树。
2.epoll反应堆reactor模式
文件描述符 事件 回调函数 封装在一起
结构体来封装 反应堆复杂版代码 反应堆多了回调函数是结构体将文件描述符事件回调函数封装一起指针的形式 3.线程池
线程池,事先创建几个线程,,不停取任务,如果没有任务休眠,省去了不停的创建线程销毁销毁线程的事件和资源
注意: 线程池 处理的任务,所需要处理的时间必须很短
一个锁
两个条件变量
循环队列 3.UDP和TCP TCP: 传输控制协议 安全可靠 丢包重传 面向连接(电话模型)
UDP: 用户数据报协议 不安全不可靠 丢包不重传 快 不面向连接(邮件模型) tcp通信流程: 服务器: 创建流式套接字 绑定 监听 提取 读写 关闭
客户端: 创建流式套接字 连接 读写 关闭
收发数据:
read recv
ssize_t recv(int sockfd, void *buf, size_t len, int flags);//flagsMSG_PEEK 读数据不会删除缓冲区的数据
write send
ssize_t send(int sockfd, const void *buf, size_t len, int flags);//flags1 紧急数据 udp通信流程
服务器: 创建报式套接字 绑定 读写 关闭
客户端: 创建报式套接字 读写 关闭
发数据:
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen);
dest_addr: 目的地的地址信息
addrlen: 结构体大小
收数据: ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);
src_addr: 对方的地址信息
addrlen: 结构体大小的地址 4.创建报式套接字
socket
int socket(int domain, int type, int protocol);
参数: domain : AF_INET type :SOCK_DGRAM protocol :0 5.创建本地套接字
unix domain socket
本地套接字通信
全双工
套接字用文件来标识,这个文件在绑定之前是不能存在 创建本地套接字
绑定
监听
提取
读写
关闭
6.创建本地套接字用于tcp通信
int socket(int domain, int type, int protocol);
参数: domain : AF_UNIX type :SOCK_STREAM protocol : 0 绑定
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen); sockfd: 本地套接字
addr: 本地套接字结构体地址
struct sockaddr_un { sa_family_t sun_family; /* AF_UNIX */ char sun_path[108]; /* pathname *///文件的路径名 };
addrlen: sockaddr_un大小 提取
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen); addr: struct sockaddr_un 结构体地址 需要注意的点:
客户端可以隐式绑定,但是服务器不可以
绑定指定文件时m,这个文件必须不存在,如果存在绑定失败 7. libevent和安装
网络的事件库
跨平台,支持多种多路io复用
核心: 以事件驱动(触发),回调 安装libevent
解压:
tar -xzvf libevent-2.0.22-stable.tar.gz -C ./install
执行configure ,检测环境生成makefile
./configure
编译
sudo make
安装
sudo make install
库的路径: /usr/local/lib 头文件目录: /usr/local/include 编译时需要指定库名 -levent
8.libevent的使用
创建event_base根节点 struct event_base *event_base_new(void);
返回值值就是event_base根节点地址 释放根节点 void event_base_free(struct event_base *); 循环监听 int event_base_dispatch(struct event_base *base);
相当于 while(1){epoll_wait}循环监听 退出循环监听
int event_base_loopexit(struct event_base *base, const struct timeval *tv); //等待固定时间之后退出 int event_base_loopbreak(struct event_base *base);//立即退出
9.libevent时间触发流程 10.libevent流程以及各个函数
初始化上树节点 struct event *event_new(struct event_base *base, evutil_socket_t fd, short events, event_callback_fn cb, void *arg);
参数: base: event_base根节点
fd: 上树的文件描述符
events: 监听的事件 #define EV_TIMEOUT 0x01 //超时事件
#define EV_READ 0x02 //读事件
#define EV_WRITE 0x04 //写事件
#define EV_SIGNAL 0x08 //信号事件
#define EV_PERSIST 0x10 //周期性触发 #define EV_ET
cb: 回调函数
typedef void (*event_callback_fn)(evutil_socket_t fd, short events, void *arg);
arg: 传给回调函数的参数
返回值: 初始化好的节点的地址 节点上树 int event_add(struct event *ev, const struct timeval *timeout); ev: 上树节点的地址
timeout: NULL 永久监听 固定时间 限时等待 下树 int event_del(struct event *ev);
ev: 下树节点的地址 释放节点 void event_free(struct event *ev);
总结 epoll工作模式水平触发边沿触发水平触发在读缓冲区只要有数据就触发边沿触发在读缓冲区来一次数据触发一次一次性读完数据写缓冲区水平触发只要可写就触发边沿触发有数据变化就触发创建lfd,监听创建树epfd写epoll_event事件事件是结构体ev.data.fdev.events(EPOLLIN 或者EPOLLOUT)epoll_ctl对文件描述符对上树EPOLL_CTL_ADD或者下树EPOLL_CTL_DEVepoll_wait监听返回值是变化的数量先判断lfd变化的操作是创建新的cfd然后再将其上树注意设置非阻塞再判断cfd变化的操作要设置一个标志位一次性读完数据别忘记关闭文件描述符和下树。
epollreactor模式使用的是结构体有事件文件描述符回调函数指针形式
tcp传输控制协议安全可靠丢包重传面向连接udp用户数据报协议与tcp相反tcp是流式套接字udp是报式套接字要注意两者客户端服务端的区别
创建udp套接字注意是SOCK_DGRAM
创建本地套接字就是与tcp相比缺少了连接步骤
本地套接字需要自定一个路径生成文件最后执行文件如果之前存在文件需要删除在运行
libevent网路事件库支持多路io复用以事件驱动触发事件回调
libevent使用event_base_new创建新节点event_base_free释放节点event_base_dispatch循环监听
libevent流程event_new新建节点节点上树event_add监听event_del下树event_free节点释放