在Ruby脚本中,我遇到套接字连接问题。 我正在做的是以下内容:
基本上我是两个服务器之间的桥梁。
代码如下所示:
require 'uri'
require 'net/http'
require 'json'
@connection1 = Net::HTTP.start 'server1.com'
@connection2 = Net::HTTP.start 'server2.com'
# reads data from server 1 as it comes and sends it to server 2
Thread.new{
while JSON.parse(@connection1.post('/receive').body) !nil
@connection2.post '/send', JSON.parse(@connection1.post('/receive').body)
end
}
# reads data from server 2 as it comes and sends it to server 2
while JSON.parse(@connection2.post('/receive').body) !nil
@connection1.post '/send', JSON.parse(@connection2.post('/receive').body)
end
# Thread.join
# not actually needed because the two connections are supposed to continuously stream data
但是,只要其中一个连接收到数据并尝试将其发送到另一个连接,我就会收到以下错误:
非套接字上的套接字操作 - Errno :: ENOTSOCK
更多深层堆栈跟踪:
C:/Dev/Ruby24-x64/lib/ruby/2.4.0/net/protocol.rb:176:在 wait_readable':非套接字上的套接字操作。 (错误:: ENOTSOCK) 来自C:/Dev/Ruby24-x64/lib/ruby/2.4.0/net/protocol.rb:176:在'rbuf_fill'中 来自C:/Dev/Ruby24-x64/lib/ruby/2.4.0/net/protocol.rb:154:在'readuntil'中 来自C:/Dev/Ruby24-x64/lib/ruby/2.4.0/net/protocol.rb:164:在'readline'中 来自C:/Dev/Ruby24-x64/lib/ruby/2.4.0/net/http/response.rb:40:in 'read_status_line' 来自C:/Dev/Ruby24-x64/lib/ruby/2.4.0/net/http/response.rb:29:in"read_new' 来自C:/Dev/Ruby24-x64/lib/ruby/2.4.0/net/http.rb:1446:在'transport_request'中的块中 来自C:/Dev/Ruby24-x64/lib/ruby/2.4.0/net/http.rb:1443:'catch' 来自C:/Dev/Ruby24-x64/lib/ruby/2.4.0/net/http.rb:1443:在'transport_request'中 来自C:/Dev/Ruby24-x64/lib/ruby/2.4.0/net/http.rb:1416:在'request'中 来自C:/Dev/Ruby24-x64/lib/ruby/2.4.0/net/http.rb:1430:在'send_entity'中 来自C:/Dev/Ruby24-x64/lib/ruby/2.4.0/net/http.rb:1218:在'post'
那么您认为我做错了什么?
我应该补充一点,由于我无法控制的原因,两个远程服务器配置为在与POST联系而不是GET时提供数据。
答案 0 :(得分:3)
两个线程之间缺少任何类型的同步,Net::HTTP
不是线程安全的。
这里可能发生的是你在一个线程中调用@connection1.post /receive
,表示线程被暂停,第二个线程在@connection1.post /send
仍被使用时尝试使用connection1
。
另一个问题是您的代码在效率低下,每个线程发出两个/receive
请求以获取信息。
while JSON.parse(@connection1.post('/receive').body) !nil
@connection2.post '/send', JSON.parse(@connection1.post('/receive').body)
end
这使得总共有三个请求
可能是
while True
result = JSON.parse(@connection1.post('/receive').body)
break if result.nil?
@connection2.post '/send', result)
end
这使得总共有两个请求
使用Mutex
确保在connection1
发送/接收请求时,没有其他线程接触它。
require 'uri'
require 'net/http'
require 'json'
@connection1 = Net::HTTP.start 'server1.com'
@connection2 = Net::HTTP.start 'server2.com'
connection_1_lock = Mutex.new
connection_2_lock = Mutex.new
# reads data from server 1 as it comes and sends it to server 2
Thread.new do
while True
receive_result = nil
connection_1_lock.synchronize do
receive_result = JSON.parse(@connection1.post('/receive').body)
end
connection_2_lock.synchronize do
@connection2.post '/send', receive_result
end
end
end
Thread.new do
while True
receive_result = nil
connection_2_lock.synchronize do
receive_result = JSON.parse(@connection2.post('/receive').body)
end
connection_1_lock.synchronize do
@connection1.post '/send', receive_result
end
end
end
我相信上面的代码应该可以解决您的问题,但我无法保证。并发编程很难。
我建议您阅读并发/多线程编程及其缺陷。网上有很多Ruby资源。
由于Ruby在Mutex
上的文档非常糟糕,我会在这里无耻地插入我自己的文章并建议你阅读它:
https://dev.to/enether/working-with-multithreaded-ruby-part-i-cj3(“如何保护自己”一节介绍了互斥体)