相关知识点简介: 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 模式下,socketEPOLLIN 和 EPOLLOUT 是何时触发的? 由于epollin比较简单,我们先来看这个。 根据epoll相关的man文档我们可以知道,epollin表示有数据可读,所以它发生的时间必然是有新的tcp数据到来。 我们来写段代码验证下: #include <arpa/inet.h> #include <assert.h> #include <errno.h> #include <fcntl.h&gt 代理充当用户与网站之间的中介服务器,通过发送和接收数据请求来处理 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():