我在与EventMachine的UDP连接上尝试设置套接字选项(特别是SO_REUSEADDR)。原样,代码片段可以正常工作。当第二个open_datagram_socket
取消注释时,它将失败并显示以下错误:
eventmachine.rb:844:在`open_udp_socket'中:没有数据报套接字(RuntimeError)
从查看源代码看,如果失败则看起来只返回null,这并不奇怪。似乎套接字选项没有正确设置,但我不熟悉库或ruby或socket编程,以了解我是否做错了什么。我无法想象图书馆不支持这样的东西,但我猜是可能的。
如何让SO_REUSEADDR与数据报套接字一起使用?
require 'eventmachine'
class PassThruServer < EM::Connection
def initialize
set_sock_opt Socket::SOL_SOCKET, Socket::SO_REUSEADDR, true
end
def post_init()
# too late?
# set_sock_opt Socket::SOL_SOCKET, Socket::SO_REUSEADDR, true
end
def receive_data(data)
puts "PT: "+ data.to_s()
send_datagram data, "localhost", 6060
end
end
class MessagePrinter < EM::Connection
def receive_data(data)
puts "MP: "+ data.to_s()
end
end
EM.run do
# pass through
EM.open_datagram_socket "localhost", 5050, PassThruServer
# EM.open_datagram_socket "localhost", 5050, PassThruServer
# test consumer
EM.open_datagram_socket "localhost", 6060, MessagePrinter
# test producer
EM.open_datagram_socket "localhost", nil do |conn|
i = 1
EM.add_periodic_timer(3) do
data = "message: "+ i.to_s() +"\n"
conn.send_datagram data, "localhost", 5050
i += 1
end
end
end
看起来TCP可能总是使用SO_REUSEADDR。我没有看到UDP甚至初始化套接字选项。据我所知,它们必须在套接字实际打开之前设置好吗?
我并没有真正理解ruby的C绑定来验证我正在寻找合适的地方。
答案 0 :(得分:1)
我能够使用以下补丁创建套接字。然而,我无法让每个套接字都收到数据的副本。
*** em.cpp Tue Oct 25 10:52:22 2011
--- em_.cpp Tue Oct 25 10:51:38 2011
*************** EventMachine_t::OpenDatagramSocket
*** 1572,1577 ****
--- 1572,1578 ----
const unsigned long EventMachine_t::OpenDatagramSocket (const char *address, int port)
{
unsigned long output_binding = 0;
+ int one = 1;
int sd = socket (AF_INET, SOCK_DGRAM, 0);
if (sd == INVALID_SOCKET)
*************** const unsigned long EventMachine_t::Open
*** 1606,1611 ****
--- 1607,1615 ----
goto fail;
}
+ if (setsockopt (sd, SOL_SOCKET, SO_REUSEADDR, (char*) &one, sizeof(one)) < 0)
+ goto fail;
+
if (bind (sd, (struct sockaddr*)&sin, sizeof(sin)) != 0)
goto fail;
我认为我的用例根本没有被图书馆的作者考虑过。需要设置的另一个套接字选项是IP_ADD_MEMBERSHIP
。它可能很容易被攻入C层,我猜。但是,我会失去尝试将它暴露给红宝石层。我认为这超出了我的实际范围。
我怀疑使用vanilla ruby库更合适。