epoll_wait()接收socket关闭两次(read()/recv()返回0)

2024-04-09

我们有一个使用 epoll 来侦听和处理 http 连接的应用程序。有时 epoll_wait() 会连续两次收到 fd 上的 close 事件。含义:epoll_wait() 返回连接 fd,其中 read()/recv() 返回 0。这是一个问题,因为我将 malloc:ed 指针保存在 epoll_event 结构(struct epoll_event.data.ptr)中,并且在 fd 时释放该指针(套接字)第一次被检测为关闭。第二次就崩溃了

这个问题在实际使用中很少出现(除了一个站点,该站点实际上每台服务器大约有 500-1000 个用户)。我可以使用每秒超过 1000 个并发连接的 http siege 来复制该问题。在这种情况下,应用程序段错误(由于无效指针)非常随机,有时在几秒钟后,通常在几十分钟后。我已经能够以每秒更少的连接来复制该问题,但为此我必须运行该应用程序很长时间、很多天,甚至几周。

所有新的accept()连接fd:s都被设置为非阻塞,并以一次性、边缘触发的方式添加到epoll中,并等待read()可用。那么为什么当服务器负载很高时,epoll 认为我的应用程序没有收到关闭事件并将新的事件放入队列?

epoll_wait() 在它自己的线程中运行,并将 fd 事件排队以在其他地方处理。我注意到有多个关闭传入,简单的代码检查是否有事件从 epoll 到同一个 fd 连续两次发生。它确实发生了,并且两者都关闭的事件(recv(..,MSG_PEEK)告诉我这一点:))。

epoll fd 创建:


epoll_create(1024);  

epoll_wait() 运行如下:


epoll_wait(epoll_fd, events, 256, 300);  

在accept()之后新的fd被设置为非阻塞:



int flags = fcntl(fd, F_GETFL, 0);
err = fcntl(fd, F_SETFL, flags | O_NONBLOCK);
  

新的fd被添加到epoll中(客户端是malloc:ed结构指针):



static struct epoll_event ev;
ev.events = EPOLLIN | EPOLLONESHOT | EPOLLET;
ev.data.ptr = client;
err = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, client->fd, &ev;);
  

并且接收并处理来自fd的数据后,重新武装(当然是从EPOLLONESHOT开始)。起初我没有使用边缘触发和非阻塞 io,但我对其进行了测试并使用它们获得了很好的性能提升。不过,这个问题在添加它们之前就存在。顺便提一句。 shutdown(fd, SHUT_RDWR) 用于其他线程,当服务器由于某些 http 错误等而需要关闭 fd 时,触发通过 epoll 接收的正确关闭事件(我实际上不知道这是否是正确的方法)这样做,但效果很好)。


一旦第一个 read() 返回 0,这意味着连接已被对等方关闭。为什么内核会在这种情况下生成 EPOLLIN 事件?好吧,当您仅订阅 EPOLLIN 时,没有其他方法可以指示套接字关闭。您可以添加 EPOLLRDHUP,这与检查 read() 返回 0 基本相同。但是,请确保测试此标志before您测试 EPOLLIN。

  if (flag & EPOLLRDHUP) {
     /* Connection was closed. */
     deleteConnectionData(...);
     close(fd); /* Will unregister yourself from epoll. */
     return;
  }

  if (flag & EPOLLIN) {
    readData(...);
  }

  if (flag & EPOLLOUT) {
    writeData(...);
  }

我订购这些块的方式是相关的,并且return对于EPOLLRDHUP也很重要,因为deleteConnectionData()可能已经破坏了内部结构。由于 EPOLLIN 也是在关闭的情况下设置的,这可能会导致一些问题。忽略 EPOLLIN 是安全的,因为它无论如何都不会产生任何数据。对于 EPOLLOUT 也是如此,因为它从不与 EPOLLRDHUP 一起发送!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

epoll_wait()接收socket关闭两次(read()/recv()返回0) 的相关文章

  • 如何模拟客户端和服务器之间的套接字断开连接(在 Windows 上)?

    我已经实现了一种 心跳解决方案 我想看看在实际情况下网络 故障 时会发生什么 特别是当套接字上没有流量时发生这种情况 问题 我只有一台电脑 我在windows java上 我想简单地拔掉网线 停用网卡不会影响这两个进程 因为它们在同一个盒子
  • PHP 上的多个 TCP 套接字请求

    是否可以使用 PHP 上的套接字服务器接受多个请求 并行 如果可以的话 怎样做 普通的 PHP 脚本无法接收多个请求 但如果你真的计划创建一个套接字服务器 作为 cmdline php 脚本启动 那么是的 这是可能的 调查http pear
  • Python中的非阻塞套接字?

    是我 还是我找不到关于Python中非阻塞套接字的好教程 我不确定如何准确地工作 recv和 send在里面 根据 python 文档 至少是我的理解 recv ed or send ed 数据可能只是部分数据 那么这是否意味着我必须以某种
  • 套接字是否可以仅针对 recv() 函数设为非阻塞?

    我希望能够打电话recv 不必阻塞 所以我想让它成为非阻塞 但我不希望它在发送数据时是非阻塞的 那么能否将套接字设为非阻塞 recv 函数 或者阻塞 非阻塞模式是否影响所有套接字函数 对于 Windows 您可以使用ioctlsocket
  • 确定用winsock(FIONWRITE)可以发送多少字节?

    通过 select 我可以确定是否可以在不阻塞的情况下接收或发送任何字节 通过这个函数 我可以确定可以接收多少字节 function BytesAvailable S TSocket Integer begin if ioctlsocket
  • 由于权限被拒绝,无法绑定到某些端口

    在过去 3 个月左右的时间里 我遇到了随机错误 无法绑定身份服务器在本地开发工作站上运行的特定端口 起初我以为是我的机器坏了 所以我重置了所有东西 这在两个月内解决了这个问题 现在它又回来了 与此同时 其他开发人员也看到了同样的问题 我们所
  • 带代理的 PHP CURL 导致套接字上的 CLOSE_WAIT

    我正在使用 PHPcurl 库来建立连接并从 WEB 检索内容 通常 我有多个 SOCKS5 代理服务器在 localhost 上运行 端口从 10300 到 10350 PHP 随机选择一个端口 My code ch curl init
  • 我可以设置默认的全局 Java 套接字超时吗?

    我遇到了一个问题 应用程序中涉及 http 和 ftp 连接的各个位置在 java net SocketInputStream socketRead0 上无限期地挂起 在终止 java 进程之前一次观察几个小时 我想全局覆盖默认的套接字超时
  • C:epoll和多线程

    我需要创建专门的 HTTP 服务器 为此我计划使用 epoll sycall 但我想利用多个处理器 核心 但我无法提出架构解决方案 ATM我的想法如下 使用自己的epoll描述符创建多个线程 主线程接受连接并将它们分配给线程epoll 但还
  • 关闭/清理“混合”文件描述符/套接字

    当我使用accept 创建一个套接字并使用fdopen 从中创建一个文件时 我需要做什么来清理所有内容 我是否需要对 FILE 执行 fclose 对套接字执行 shutdown 和 close 还是只需要 shutdown 和 或 clo
  • 使用 asyncore 读取网站

    我想异步阅读一个网站 据我所知 这是不可能的 urllib 现在我尝试使用普通套接字进行阅读 但是 HTTP 给我带来了麻烦 我遇到了各种时髦的编码 例如传输编码 分块 必须手动解析所有这些东西 我现在想编码 C 而不是 python 难道
  • 我该怎么做才能完全关闭与mcu的tcpClient连接?

    我现在正在研究与 ESP32 中运行的 tcp 服务器的 tcp 套接字连接 通信工作正常 但我无法关闭连接 在搜索关闭 重置 tcpClient 上的解决方案后 似乎关闭 tcpClient 的正确方法应该是 tcpClient GetS
  • 根据 TCP 的 C++ 函数

    我正在使用 recv 函数 C 来获取有关网络问题的指示 在这种情况下它返回负值 看这里 https www rfc editor org rfc rfc1122 page 100 https www rfc editor org rfc
  • C 获取监听服务器的IP

    我正在使用 C 套接字编写客户端 服务器程序 我指定服务器可以通过使用 sockaddr in sin addr s addr 中的 INADDR ANY 侦听任何网络接口 这相当于 IP 0 0 0 0 我可以获取服务器正在监听的实际IP
  • Java心跳设计

    我需要在我的 Java 项目上实现一个心跳系统 3 5 个客户端和 1 个服务器 但我有一些问题 1 客户端需要有 2 个套接字吗 1 用于心跳 1 用于接收我的软件的正常消息 2 我看到在特定情况下 当客户端滞后时 客户端不会收到消息 如
  • Android Socket + ObjectOutputStream 无法正常工作

    我正在开发一个客户端 服务器程序 其中客户端是 Android 设备 服务器有一个从输入流读取对象的侦听器类 我为另一台计算机创建了一个客户端软件 该软件通过本地网络发送一个小对象 计算机到计算机工作得很好 我读取了该对象并打印了内容 但是
  • Socket.*Async 方法是线程化的吗?

    我目前正在尝试找出最小化 TCP 主服务器中使用的线程数量的最佳方法 以便最大限度地提高性能 由于我最近阅读了大量 C 5 0 的新异步功能 异步并不一定意味着多线程 这可能意味着将有限状态对象分成较小的块 然后通过交替与其他操作一起进行处
  • 在 PCL 中使用 System.Net.Sockets(.Net 4.5 + 电话 8)

    我现有的 Net 库已经适用于 Net 4 5 和 Windows Phone 8 现在我想将其转换为可移植类库 突然我无法使用System Net Sockets不再了 我只检查了 Net 4 5和Windows Phone 8 未选择X
  • Rails 应用程序中的持久 TCP 连接

    我有一个在服务器上运行的第三方应用程序 它对客户端进行身份验证并返回响应 我的问题是 对于我收到 Rails 应用程序的每个请求 我都需要建立 TCP 连接并获取数据 是否可以有一个持久连接 以便我可以减少建立连接的开销 我希望你使用的是
  • Linux 中 AF_UNIX 数据报消息的最大大小是多少?

    目前我已达到 130688 字节的硬限制 如果我尝试在一条消息中发送更大的内容 我会收到一条消息ENOBUFS error 我已经检查过net core rmem default net core wmem default net core

随机推荐

  • 如何将字符串转换为 CLLocationDegrees Swift 2

    我正在尝试转换从 Firebase 检索的字符串并将其添加为 Google 地图上的多个注释 不幸的是 每当我的应用程序执行当前代码时就会崩溃 ref FIRDatabase database reference ref child Loc
  • 如何在 Scala 中使用 JUnit ExpectedException?

    我希望能够使用 JUnit 4 7预期异常 Rule http kentbeck github com junit javadoc latest org junit rules ExpectedException html在斯卡拉 然而 它
  • 无法在 iOS 上将 CIImage 保存到文件而不发生内存泄漏

    下面的代码片段保存了一个CIImage到磁盘使用UIImage void applicationWillResignActive UIApplication application NSString filename Test png UI
  • HibernateTemplate 可以与 Envers 一起使用吗?如果是这样,怎么办?

    我正在尝试在一个也使用 Hibernate 和 Spring 的项目上使用 Envers 我非常欣赏 HibernateTemplate 提供的代码减少功能 我在 JPA 下配置了 Envers 经过一些调整后 我能够通过 EnversHi
  • Shell_exec 与 git pull ?

    我正在建立一个 github 帐户 与一些朋友一起开发一个小项目 我希望我的家用机器能够通过 php 执行 git pull 这样我们只需调用这个小 php 文件即可使机器保持最新状态 截至目前 这工作完美 我得到了输出 我在正确的目录中
  • 如何将我的 Kivy 客户端连接到服务器(TCP、套接字)

    因此 作为我的项目 2D 多人纸牌游戏 的一部分 我已经弄清楚如何在线托管和运行服务器脚本 我的计划是让两个单独的 kivy 客户端连接到服务器 这只是一个带有命令的脚本 但是我对操作顺序有些困惑 因为我think客户端连接可能与消息循环发
  • 查找 Javascript 对象中属性的交集

    大家好 我想我有以下两个对象 var obj1 one 232 two 3123 three 3232 var obj2 one 323 three 3444 seven 32 我正在尝试编写一个函数 该函数将返回两个对象中的属性 假设我始
  • 使 ViewGroup 在 Android 上可点击

    我有一个 ViewGroup LinearLayout 其中包含几个 TextView 和一个 ImageView 我想让整个组都可以点击 我尝试过这样的事情 viewGroup setOnClickListener new OnClick
  • HTML 5 游戏是否使用 Canvas 和 Javascript?这种情况下如何防止作弊呢?

    HTML 5 游戏是否使用 Canvas 和 Javascript 这种情况下如何防止作弊呢 例如 如果用户使用 GreaseMonkey 或某些工具来更改脚本 使其每次只向服务器报告完美的游戏分数 该怎么办 我会用我自己的问题来回答你的问
  • 如何使用gdb来探索堆栈/堆?

    谁能给我一个快速概述 给我指出一种检查 C 程序堆栈 和堆 的方法的文档 我认为这应该用 GDB 来完成 但如果有其他更直接的替代方案 那么也应该没问题 Thanks 您可以使用 x 命令转储原始内存 因此 如果您想查看堆栈或堆的位 请尝试
  • gcc 通过 homebrew 没有 --without-multilib 选项

    我想在 Python 3 5 中安装 xgboost 这个需要gcc支持 fopenmp选项 默认gcc不支持 所以我正在使用 brew install gcc without multilib 但我得到Warning gcc this f
  • 将本地文件的内容读取到 Rails 中的变量中

    我想做的就是从本地文件中获取所有内容并将其存储在变量中 如何 File read icon full filename each l r l 只给我一部分 在 PHP 中 我刚刚使用file get contents data File r
  • 硬币兑换 DP 解决方案以跟踪硬币

    尝试为一般的硬币找零问题编写一个 DP 解决方案 该解决方案还可以跟踪使用了哪些硬币 到目前为止 我已经可以为我提供所需的最低数量的硬币 但无法弄清楚如何获取使用了哪些硬币以及使用了多少次 如果使用硬币 我尝试设置另一个带有值的表 布尔值
  • Javascript 域模型对象约定

    如果我必须在 C 中创建域模型对象 我可能会这样做 public class Person Public string Name get set Public string Gender get set Public int Age get
  • 使用文本框自动滚动到底部

    我有一个由 ms access 制作的 mdb 文件 它有一个表单 表单内部有一个大文本框 制作此文本框的目的是通过在文本框中添加消息来显示某些工作的进度 txtStatus value txtStatus value Doing some
  • 如何通过 COM 公开 .netstandard2.0 库以便在 VB6 中使用?

    我有一个 dotnet 核心库 一个框架 4 7 2 库和一个 vb6 应用程序 我想编写一个公共库供他们所有人访问 因此选择 netstandard2 0 我尝试了 netstandard2 0 库和 vb6 之间的 4 7 2 框架包装
  • Grails:两个域对象之间的多重关系

    我正在尝试在 Grails 中的两个域类之间实现两种不同类型的关系 考虑以下 我有两个域类 一个作者类和一个书籍类 其中一个作者拥有很多书籍 class Author String name class Book String title
  • 在 SQL Management studio 中更改 CommandTimeout

    如何更改 SQL Management Studio 中的 CommandTimeout 如果您在使用表设计器时遇到超时 请更改工具 gt 选项 gt 设计器 gt 表和数据库设计器下的 事务超时时间 值 这将消除此消息 超时已到 操作完成
  • pandas 六个月的日期范围

    所以 这是我的数据框 PatientNumber QT Answer Answerdate DiagnosisDate 1 1 transferring No 2017 03 03 2018 05 03 2 1 preparing food
  • epoll_wait()接收socket关闭两次(read()/recv()返回0)

    我们有一个使用 epoll 来侦听和处理 http 连接的应用程序 有时 epoll wait 会连续两次收到 fd 上的 close 事件 含义 epoll wait 返回连接 fd 其中 read recv 返回 0 这是一个问题 因为