EPOLLRDHUP

  EPOLLRDHUP

在使用epoll的情况下:服务器端运行以下程序,当客户端调用close()关闭后,服务器端会执行满足 evs[i].events & EPOLLIN 条件的代码

for (;;)
{
  int n = epoll_wait(epfd, evs, 20, -1);
  for (int i = 0; i < n; i++)
  {
    if (evs[i].events & EPOLLIN)
    {
      //client close之后,这里收不到客户端终止的信号???
    }
    if (evs[i].events & EPOLLOUT)
    {

    }
    if (evs[i].events & EPOLLERR)
    {

    }
    if (evs[i].events & EPOLLHUP)
    {

    }
  }
}

明明是客户端请求断开,系统却报告一个错误,但从用户角度来看请求的结果正常返回,没有任何问题。
通过查询资料,对这个现象深入分析后发现,这是一个基于 epoll 的连接池实现上的问题。
首先解释一下导致这个现象的原因:

  在使用 epoll 时,对端正常断开连接(调用 close()),在服务器端会触发一个 epoll 事件。在低于 2.6.17 版本的内核中,这个 epoll 事件一般是 EPOLLIN,即 0x1,代表连接可读。连接池检测到某个连接发生 EPOLLIN 事件且没有错误后,会认为有请求到来,将连接交给上层进行处理。这样一来,上层尝试在对端已经 close() 的连接上读取请求,只能读到 EOF,会认为发生异常,报告一个错误。

  因此在使用 2.6.17 之前版本内核的系统中,我们无法依赖封装 epoll 的底层连接库来实现对对端关闭连接事件的检测,只能通过上层读取数据时进行区分处理。

  2.6.17 版本内核中增加了 EPOLLRDHUP 事件,代表对端断开连接。在使用 2.6.17 之后版本内核的服务器系统中,对端连接断开触发的 epoll 事件会包含 EPOLLIN | EPOLLRDHUP,即 0x2001。有了这个事件,对端断开连接的异常就可以在底层进行处理了,不用再移交到上层。

  注意,在使用 2.6.17 之前版本内核的系统中,sys/epoll.h 的 EPOLL_EVENTS 枚举类型中是没有 EPOLLRDHUP 事件的,所以带 EPOLLRDHUP 的程序无法编译通过。

时间: 2024-10-06 00:07:43

EPOLLRDHUP的相关文章

linux IO复用(epoll)小记

一.epoll简介 epoll是Linux内核为处理大批量文件描述符而作了改进的poll, 是Linux下多路复用IO接口select/poll的增强版本, 它能显著提高程序在大量并发连接中只有少量活跃的情况下的系统CPU利用率.另一点原因就是获取事件的时候, 它无须遍历整个被侦听的描述符集, 只要遍历那些被内核IO事件异步唤醒而加入Ready队列的描述符集合就行了. 二.epoll的API函数 1. 句柄创建函数 int epoll_create(int size); 创建一个epoll的句柄

web服务器

// myserver_threadpool.h#ifndef MYSERVER_THREADPOOL_H #define MYSERVER_THREADPOOL_H #include<list> #include<cstdio> #include<exception> #include<pthread.h> #include"locker.h" template<typename T> class myserver_thre

I/O多路转接-epoll

By francis_hao    Aug 5,2017 APUE讲多路转接的章节介绍了select.pselect和poll函数.而epoll是linux内核在2.5.44引入的.在glibc 2.3.2添加了支持. epoll_create – 打开一个epoll文件描述符 epoll_ctl – 控制epoll文件描述符接口 epoll_wait – 在epoll文件描述符上等待一个I/O事件 概述 #include <sys/epoll.h>int epoll_create(int s

centos 7.0 nginx 1.7.9成功安装过程

centos 7.0根目录 的目录构成 [[email protected] /]# lsbin dev home lib64 mnt proc run srv tmp varboot etc lib media opt root sbin sys usr 首先下载 nginx 官网 http://nginx.org/en/download.html 由于不太熟悉centos 7.0 的目录 先直接安装到usr目录下 usr/local/src [[email protected] /]# cd

Nginx 事件基本处理流程分析

说明:本文章重点关注事件处理模型,顺便介绍相关的结构体,其他的结构体不做介绍.有兴趣的同学可以去http://tengine.taobao.org/book/查找更多资料.Tengine应该是淘宝基于Nginx自己做的修改.这个地址的文档还在不断的完善更新中. 程序流程图: 说明: 一.进程生成顺序 1.main(src/core/nginx.c)函数启动ngx_master_process_cycle,启动主服务进程. 2.ngx_master_process_cycle(src/os/uni

服务器后台TCP连接存活问题

0. 背景 公司的服务器后台部署在某一个地方,接入的是用户的APP,而该地方的网络信号较差,导致了服务器后台在运行一段时间后用户无法接入,那边的同事反馈使用netstat查看系统,存在较多的TCP连接. 1. 问题分析 首先在公司内部测试服务器上部署,使用LoadRunner做压力测试,能正常运行,然后那边的同事反馈该地方信号较差.考虑到接入的问题,有可能接入进程的FD资源耗尽,导致accept失败.推论的依据是对于TCP连接来说,如果客户端那边由于一些异常情况导致断网而未能向服务器发起FIN关

Tinywebserver:一个简易的web服务器

这是学习网络编程后写的一个练手的小程序,可以帮助复习I/O模型,epoll使用,线程池,HTTP协议等内容. 程序代码是基于<Linux高性能服务器编程>一书编写的. 首先回顾程序中的核心内容和主要问题,最后给出相关代码. 0. 功能和I/O模型 实现简易的HTTP服务端,现仅支持GET方法,通过浏览器访问可以返回相应内容. I/O模型采用Reactor(I/O复用 + 非阻塞I/O) + 线程池. 使用epoll事件循环用作事件通知,如果listenfd上可读,则调用accept,把新建的f

centos 1.7 安装nginx 1.9.10

可以参考以前安装成功的案例 centos 7.0 nginx 1.7.9成功安装过程 官网下载 http://nginx.org/en/download.html nginx下载位置 /usr/local/ nginx 安装目录 /usr/etc/nginx1910 nginx path prefix: "/usr/etc/nginx1910" nginx binary file: "/usr/etc/nginx1910/sbin/nginx" nginx conf

lua-epoll 模块简单分析

这个模块是把Linux下的epoll操作按照Lua Cfunction 的格式封装出来,供lua使用. Lua要求每一个扩展模块,必须提供luaopen_XXX(lua_State *L) 作为模块的入口函数,此函数会在require加载模块时被调用到.我们就从这个函数开始分析: static const struct luaL_Reg epoll[]={     {"setnonblocking",setnonblocking},     {"create",ep