Index: ext/socket/lib/socket.rb =================================================================== --- ext/socket/lib/socket.rb (revision 39728) +++ ext/socket/lib/socket.rb (working copy) @@ -45,7 +45,7 @@ class Addrinfo # If a block is given the created socket is yielded for each address. # def connect_internal(local_addrinfo, timeout=nil) # :yields: socket - sock = Socket.new(self.pfamily, self.socktype, self.protocol) + sock = self.unbound_socket begin sock.ipv6only! if self.ipv6? sock.bind local_addrinfo if local_addrinfo @@ -172,7 +172,7 @@ class Addrinfo # } # def bind - sock = Socket.new(self.pfamily, self.socktype, self.protocol) + sock = self.unbound_socket begin sock.ipv6only! if self.ipv6? sock.setsockopt(:SOCKET, :REUSEADDR, 1) @@ -189,7 +189,7 @@ class Addrinfo # creates a listening socket bound to self. def listen(backlog=Socket::SOMAXCONN) - sock = Socket.new(self.pfamily, self.socktype, self.protocol) + sock = self.unbound_socket begin sock.ipv6only! if self.ipv6? sock.setsockopt(:SOCKET, :REUSEADDR, 1) @@ -205,6 +205,14 @@ class Addrinfo end end + # Creates a socket from Addrinfo that is not bound or connected. + # + # Note that you must have set a protocol family in Addrinfo.new or by using + # Addrinfo.udp or Addrinfo.tcp. + def unbound_socket + Socket.new(self.pfamily, self.socktype, self.protocol) + end + # iterates over the list of Addrinfo objects obtained by Addrinfo.getaddrinfo. # # Addrinfo.foreach(nil, 80) {|x| p x } @@ -358,7 +366,7 @@ class Socket < BasicSocket port = nil ai_list.each {|ai| begin - s = Socket.new(ai.pfamily, ai.socktype, ai.protocol) + s = ai.unbound_socket rescue SystemCallError next end Index: test/socket/test_addrinfo.rb =================================================================== --- test/socket/test_addrinfo.rb (revision 39728) +++ test/socket/test_addrinfo.rb (working copy) @@ -120,6 +120,20 @@ class TestSocketAddrinfo < Test::Unit::T s2.close if s2 && !s2.closed? end + def test_unbound_socket + s1 = Socket.new(:INET, :DGRAM, 0) + sa = Socket.sockaddr_in(0, "127.0.0.1") + ai = Addrinfo.udp("127.0.0.1", 0) + s1.bind ai + + s2 = ai.unbound_socket + s2.send("test-socket", 0, s1.getsockname) + assert_equal("test-socket", s1.recv(100)) + ensure + s1.close if s1 && !s1.closed? + s2.close if s2 && !s2.closed? + end + def test_socket_bind s1 = Socket.new(:INET, :DGRAM, 0) sa = Socket.sockaddr_in(0, "127.0.0.1")