通过 SO_RCVTIMEO 套接字选项在 Ruby 中设置套接字超时

2024-06-19

我试图通过 SO_RCVTIMEO 套接字选项在 Ruby 中设置套接字超时,但它似乎对任何最近的 *nix 操作系统都没有影响。

使用 Ruby 的 Timeout 模块不是一个选择,因为它需要为每个超时生成和连接线程,这可能会变得昂贵。在需要低套接字超时且具有大量线程的应用程序中,它本质上会降低性能。许多地方都注意到了这一点,包括堆栈溢出 https://stackoverflow.com/questions/231647/how-do-i-set-the-socket-timeout-in-ruby.

我读过 Mike Perham 关于这个主题的优秀文章here http://www.mikeperham.com/2009/03/15/socket-timeouts-in-ruby/为了将问题减少到一个可运行代码文件,创建了一个简单的 TCP 服务器示例,该服务器将接收请求,等待请求中发送的时间,然后关闭连接。

客户端创建一个socket,设置接收超时时间为1秒,然后连接到服务器。客户端告诉服务器在 5 秒后关闭会话,然后等待数据。

客户端应在一秒后超时,但在 5 秒后成功关闭连接。

#!/usr/bin/env ruby
require 'socket'

def timeout
  sock = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)

  # Timeout set to 1 second
  timeval = [1, 0].pack("l_2")
  sock.setsockopt Socket::SOL_SOCKET, Socket::SO_RCVTIMEO, timeval

  # Connect and tell the server to wait 5 seconds
  sock.connect(Socket.pack_sockaddr_in(1234, '127.0.0.1'))
  sock.write("5\n")

  # Wait for data to be sent back
  begin
    result = sock.recvfrom(1024)
    puts "session closed"
  rescue Errno::EAGAIN
    puts "timed out!"
  end
end

Thread.new do
  server = TCPServer.new(nil, 1234)
  while (session = server.accept)
    request = session.gets
    sleep request.to_i
    session.close
  end
end

timeout

我也尝试过使用 TCPSocket (自动连接)做同样的事情,并且在redis https://github.com/ezmobius/redis-rb/blob/c41bc94ea6e6eebb718428d74d22c84b6d2513a4/lib/redis/connection/ruby.rb#L44-55和其他项目。

此外,我可以通过调用来验证该选项是否已设置getsockopt像这样:

sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_RCVTIMEO).inspect

设置此套接字选项实际上对任何人都有效吗?


你可以这样做有效率的 using select来自 Ruby 的 IO 类。

IO::select需要 4 个参数。前三个是要监视的套接字数组,最后一个是超时(以秒为单位指定)。

select 的工作方式是,它通过阻塞使 IO 对象列表为给定操作做好准备,直到其中至少一个对象准备好读取、写入或想要引发错误。

因此,前三个参数对应于要监视的不同类型的状态。

  • 准备阅读
  • 准备写作
  • 有待处理的异常

第四个是您要设置的超时(如果有)。我们将利用这个参数。

Select 返回一个包含 IO 对象数组(在本例中为套接字)的数组,操作系统认为这些对象已准备好执行正在监视的特定操作。

所以 select 的返回值将如下所示:

[
  [sockets ready for reading],
  [sockets ready for writing],
  [sockets raising errors]
]

但是,选择返回nil如果给出了可选的超时值并且在超时秒内没有 IO 对象准备就绪。

因此,如果您想在 Ruby 中执行高性能 IO 超时并避免使用 Timeout 模块,您可以执行以下操作:

让我们构建一个等待的例子timeout继续阅读的秒数socket:

ready = IO.select([socket], nil, nil, timeout)

if ready
  # do the read
else
  # raise something that indicates a timeout
end

这样做的好处是不会为每次超时(如 Timeout 模块中那样)启动一个新线程,并且会使多线程应用程序具有许多超时much在 Ruby 中速度更快。

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

通过 SO_RCVTIMEO 套接字选项在 Ruby 中设置套接字超时 的相关文章

随机推荐

  • 动态字段取决于 WTForms 的先前字段

    我正在使用 WTForms 制作表格 目前 我有这个 class UploadForm flask wtf Form fichier wtforms fields FileField u Fichier description wtform
  • 相对于变换元素的绝对定位元素位置

    我重新创建了我在模板中遇到的问题 有一个nav具有position relative 在 的里面nav有一个div有两个嵌套列表 其中一个列表的位置绝对固定在列表的底部nav 当div对其应用了变换 当 的时候div在绝对和相对定位的元素之
  • 请求超级用户权限编辑文件

    我正在规划一个需要编辑系统文件的应用程序 我只能使用 root 权限编辑该文件 我有一个已 root 且安装了 Superuser apk 的开发手机 其他需要 root 的应用程序会在首次启动时请求 root 访问权限 我想做同样的事情
  • Intel 上的 gcc 中的 _mm_pause 用法

    我参考过这个网页 https software intel com en us articles benefitting power and performance sleep loops https software intel com
  • 如果 Row1 = 值 1,则更新其他行

    我有一个小的 php 脚本 用于访问 mySql 数据库 我想在数据库中插入新记录之前查看该数字 值 1 是否等于数据库中的记录 这也在第 1 行 所以我想 查看传入的电话号码是否等于数据库中的电话号码 如果是这样 则必须保持电话号码相同的
  • rightBarButtonItem 信息按钮,右侧没有空格

    我有一个UIViewController设置为在其右侧显示一个信息按钮UINavigationItem像这样 UIButton infoButton UIButton buttonWithType UIButtonTypeInfoLight
  • 异常行为

    我是 C 的新手 小代码示例如下 int main int argc char argv char ch1 int int1 cin gt gt ch1 cin gt gt int1 cout lt lt ch1 lt lt n cout
  • 如何在CloudFormation模板中描述AWS Lambda函数测试事件?

    我在 CloudFormation 模板中描述了现有的 AWS Lambda 函数 然后我面临下一个问题 在我们的 Lambda 中 我们配置了一些测试事件 这有助于我们验证一些用例 我的意思是下面屏幕截图中的功能 但我没有看到任何将这些测
  • Python3将模块从文件夹导入到另一个文件夹

    我的结构字典是 mainFolder folder1 init py file1 py file2 py folder2 init py file3 py file4 py setup py init py 我需要将 file4 py 从f
  • 在打印 CSS 上在每个页面周围绘制边框?

    打印时我需要在每个页面周围绘制边框 我最初是使用带有分页符的 div 来完成此操作 例如 media print contentContainer position inline height 98 width 100 top 0px le
  • 是否可以从另一个方法传递 args[] 来调用 main 方法?

    我试图从另一个传递参数的方法调用类的主要方法 就像从命令行运行该类时一样 有没有办法做到这一点 您可以致电main方法就像您调用任何其他 静态 方法一样 MyClass main new String arg1 arg2 arg3 Exam
  • 可升级读锁的优点?

    我想知道使用可升级读锁与执行这些步骤相比有什么优势 获取读锁 检查条件以查看是否需要进行写锁定 释放读锁 采取写锁定 执行更新 释放写锁 与获取可升级读锁相比 执行上述步骤的一个明显缺点是 步骤 3 和步骤 4 之间存在一个时间窗口 其中另
  • 自动检测内部/外部开发环境

    我们使用以下函数来自动检测我们是在内部机器上还是在实时服务器上 然后为各种组件选择适当的配置 function devIsLocal res false http host SERVER HTTP HOST if http host loc
  • 根据条件延迟 Celery 任务

    有什么办法可以根据条件延迟 Celery 任务的运行吗 在它从计划变为活动之前 我想执行快速检查 看看我的机器是否可以根据提供的参数和当时机器的状态运行该任务 如果不是 它会暂停计划队列并等待 直到满足条件 我环顾了以下几点 但似乎没有解决
  • 如果浏览器在 asp .net 中关闭,请从浏览器中注销?

    我的要求有点复杂 用户正在使用 Web 浏览器访问数据库 而在访问数据库时 如果用户关闭活动页面而不是注销会话 该会话需要自动注销 有人可以指导我如何做这个吗 我在母版页中使用了jquery onbeforeunload 我收到消息离开页面
  • 有没有办法监控页面上运行的 JavaScript 函数?

    有没有办法查看页面上正在执行哪些功能 如果我在页面上加载外部脚本 是否可以动态更改函数的功能或阻止其运行 HTML5 http www w3 org TR html5 scripting 1 html establish script bl
  • Python 内置对象的 __enter__() 和 __exit__() 在哪里定义?

    我读到每次使用 with 时都会调用该对象的 enter 和 exit 方法 我知道对于用户定义的对象 您可以自己定义这些方法 但我不明白这对于 打开 等内置对象 函数甚至测试用例是如何工作的 这段代码按预期工作 我假设它使用 exit 关
  • 有没有一种从 unsigned char* 转换为 char* 的好方法?

    那些天我读了很多关于reinterpret cast lt gt 以及应该如何使用它 并在大多数情况下避免使用它 虽然我明白使用reinterpret cast lt gt 投射自 说unsigned char to char is 实施定
  • 用于在链表中查找结点的生产代码

    我在一次采访中被问到这个问题 我被要求编写代码 用于在 O 1 空间和线性时间的生产环境中在链表 其形式为 Y 形式 双臂不一定相等 中查找结点 我想出了这个解决方案 我以前在某处见过 1 Measure lengths of both l
  • 通过 SO_RCVTIMEO 套接字选项在 Ruby 中设置套接字超时

    我试图通过 SO RCVTIMEO 套接字选项在 Ruby 中设置套接字超时 但它似乎对任何最近的 nix 操作系统都没有影响 使用 Ruby 的 Timeout 模块不是一个选择 因为它需要为每个超时生成和连接线程 这可能会变得昂贵 在需