ruby - ruby 'async/io' 和 Reactor,帮助理解示例
问题描述
我需要一些帮助来理解这里给出的基本“async/io”示例:
require 'async/io'
def echo_server(endpoint)
Async::Reactor.run do |task|
# This is a synchronous block within the current task:
endpoint.accept do |client|
# This is an asynchronous block within the current reactor:
data = client.read(512)
# This produces out-of-order responses.
task.sleep(rand * 0.01)
client.write(data.reverse)
end
end
end
def echo_client(endpoint, data)
Async::Reactor.run do |task|
endpoint.connect do |peer|
result = peer.write(data)
message = peer.read(512)
puts "Sent #{data}, got response: #{message}"
end
end
end
Async::Reactor.run do
endpoint = Async::IO::Endpoint.tcp('0.0.0.0', 9000)
server = echo_server(endpoint)
5.times.collect do |i|
echo_client(endpoint, "Hello World #{i}")
end.each(&:wait)
server.stop
end
反应堆模式(如果错了请纠正)基本上是一种同步任务的调度程序,这样在阻塞时,一个任务被挂起,另一个任务被启动,依此类推,一旦任务被解除阻塞,任务就会恢复[来源]
在给定的 github 示例中,首先定义 echo_server 返回的方法Async::Task
,并将其分配给服务器变量server
现在创建了变量,底层任务开始监听套接字并被client.read(512)
调用阻塞。它被挂起,流到达循环部分,5 个客户端Async::Task
一个一个地向套接字写入消息。
现在发生了一些我不明白的事情。服务器任务被解锁并回复第一条消息。之后它应该退出,因为没有循环。然而,它服务于所有五个请求并在此之后退出。显然有什么我错了,但我无法弄清楚。任何意见都受到高度赞赏。
解决方案
echo_client
在从循环中调用时执行 5 次。该函数调用endpoint.connect
并发送单个消息并读取单个响应。
echo_server
执行 1 次并调用endpoint.accept
为每个连接生成块。服务器读取一条消息并将其写回。
服务器任务被解锁并回复第一条消息。之后它应该退出,因为没有循环。
endpoint.accept
实现为循环:
def accept(backlog = Socket::SOMAXCONN, &block)
bind do |server|
server.listen(backlog)
server.accept_each(&block)
end
end
def accept_each(task: Task.current)
task.annotate "accepting connections #{self.local_address.inspect}"
while true
self.accept(task: task) do |io, address|
yield io, address, task: task
end
end
end
如您所见,它绑定到套接字,侦听传入连接,然后在循环中调用接受。
推荐阅读
- jquery - AngularJS,区分拖动和点击事件,给点击事件传递数据
- html - 检测引导导航栏是否折叠或没有角度
- java - 在eclipse中创建类的问题
- javascript - EventListener 不能同等地捕捉按钮
- laravel - 在 Laravel 中加密密码时出错。“有效载荷无效。”
- java - 如何监控 REST Endpoint 以获取长时间运行的作业
- java - 如何在 AppCompatActivity 之后添加多个实现?
- node.js - 在 Node.js 路由中添加 isAuthenticated 并不能防止未经身份验证的访问
- php - 关于 Laravel 中的紧凑方法
- django - 删除视图不会删除对应的对象