相关知识点简介: epoll有两个模式可以设置,一个是水平模式(level-triggered),另一个是边缘模式(edge-triggered), 区别就是水平模式可以带来事件的重复触发,而边缘模式只触发一次。举个栗子,当epoll监听的描述符发生可读事件时,比方说收到了别人发来的10个字节数据,你只读了一个字节,如果是水平触发,那么epoll将一直触发直到剩下那9个字节读完,而边缘触发呢,就是收到了一个读事件,你自己去读吧,读多少算多少,而epolll只触发一次。
而我在实际测试epoll监听udp套接字的时候,使用默认的水平触发去监听读事件,每次只读取一个字节,按道理收到多个字节epoll应该触发(trigger)多次才对,结果它只触发了一次,如图:
程序启动后监听3500端口,使用网络调试助手发3个字节到监听地址,只读取一个,结果显示epoll触发一次后就hang住
代码这样写的:
while(1) {
fds = epoll_wait(efd, epoll_events_ptr, 2, -1); //阻塞
for (i = 0; i<fds; i++)
if (epoll_events_ptr[i].events & EPOLLIN)
ret = read(fd1, buffer, 1);
if(ret != -1)
log("recv msg : %s \n", buffer);
memset(buffer, 0, BUFFER_SIZE);
同样情况下,如果监听的是标准输入的话,epoll触发了多次,如下图,代码就不贴了
两个例子流程基本一样,除了一个监听udp套接字,一个监听标准输入(STDIN_FILENO)
最后在stackoverflow上有大神解答说UDP套接字是以报文为单位的,如果一次没有读取完成,剩余数据会被丢弃,这解释了为什么epoll只触发了一次,因为在读取一个字节的时候,剩余两个字节被丢弃了。这和面向字节流的TCP套接字不同。
stackoverflow上的问题链接:
https://stackoverflow.com/questions/50938689/epoll-eventsepolllt-only-triggered-once-on-udp-socket/50939267#50939267
创建了一个linux应用&内核相关开发到讨论群:745510310 欢迎有兴趣的同学加入
本篇文章的问题是,在 EPOLLET 模式下,socket的 EPOLLIN 和 EPOLLOUT 是何时触发的?
由于epollin比较简单,我们先来看这个。
根据epoll相关的man文档我们可以知道,epollin表示有数据可读,所以它发生的时间必然是有新的tcp数据到来。
我们来写段代码验证下:
#include <arpa/inet.h>
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
代理充当用户与网站之间的中介服务器,通过发送和接收数据请求来处理 Web 浏览器和应用程序之间的通信。浏览器或服务器提交请求后,会在指定的时间段内等待响应。但在实际使用当中,许多用户都会遇到代理提示超时的情况,导致这种情况出现的原因主要有以下几种:1. 网络连接不佳糟糕的互联网连接可能是代理超时错误的原因之一。用户在发现代理提示超时后,应当先查看计算机屏幕底部的状态栏的网络连接图标,单击查看网络连接是否正常,或者是否存在某些网络设置错误的问题。2.服务器连接问题当用户从代理发送请求时,通常会在尝试连接到目标
如果主accept监听的soctet
fd也设置为非阻塞,那么单纯靠epoll事件来驱动的服务器模型会存在问题,并发压力下发现,每次accept只从系统中取得第一个,所以如果恰冯多个
连接同时触发server
fd的EPOLLIN事件,在返回的event数组中体现不出来,会出现丢失事件的现象,所以当用ab等工具简单的压载就会发现每次都会有最后几条信息得
不到处理,原因就在于此,我现在的解决
2.设置socket的属性,用setsockopt()函数,(可选)
3.往socket绑定包含 IP信息,地址信息的 struct sockaddr_in(IPv4)结构体。用bind()函数
4.循环接收消息,用recvfrom()函数
5.关闭socket套接字
客户端编程:
1.创建 UDP socket套接字,用socket函数。
2.用sendto()函数往指定的IP,地址发送信息。
1.sendto():