Issue #10203 has been updated by Akira Tanaka.


It seems net.ipv6.bindv6only affect the behavior.

```
% sudo sysctl net.ipv6.bindv6only=0
net.ipv6.bindv6only = 0
% ./ruby -vrsocket -e 'p TCPServer::new(10001); system("netstat -ln|grep 10001"); p TCPServer::new(10001); system("netstat -ln|grep 10001"); p TCPServer::new(10001)'
ruby 2.2.0dev (2014-10-13 trunk 47899) [x86_64-linux]
#<TCPServer:fd 7>
tcp        0      0 0.0.0.0:10001           0.0.0.0:*               LISTEN
-e:1:in `initialize': Address already in use - bind(2) for nil port 10001 (Errno::EADDRINUSE)
	from -e:1:in `new'
	from -e:1:in `<main>'
```

```
% sudo sysctl net.ipv6.bindv6only=1
net.ipv6.bindv6only = 1
% ./ruby -vrsocket -e 'p TCPServer::new(10001); system("netstat -ln|grep 10001"); p TCPServer::new(10001); system("netstat -ln|grep 10001"); p TCPServer::new(10001)'
ruby 2.2.0dev (2014-10-13 trunk 47899) [x86_64-linux]
#<TCPServer:fd 7>
tcp        0      0 0.0.0.0:10001           0.0.0.0:*               LISTEN
#<TCPServer:fd 8>
tcp        0      0 0.0.0.0:10001           0.0.0.0:*               LISTEN
tcp6       0      0 :::10001                :::*                    LISTEN
-e:1:in `initialize': Address already in use - bind(2) for nil port 10001 (Errno::EADDRINUSE)
	from -e:1:in `new'
	from -e:1:in `<main>'
```

This depends on OS configuration.

TCPServer.new doesn't hide this difference because some OS, such as OpenBSD, provides only the latter behavior.

I recommend Socket.tcp_server_sockets.
It returns two sockets for IPv4 and IPv6, regardless of net.ipv6.bindv6only.

```
% sudo sysctl net.ipv6.bindv6only=0
net.ipv6.bindv6only = 0
% ./ruby -rsocket -e 'p Socket.tcp_server_sockets(10001)'
[#<Socket:fd 7>, #<Socket:fd 8>]
% sudo sysctl net.ipv6.bindv6only=1
net.ipv6.bindv6only = 1
% ./ruby -rsocket -e 'p Socket.tcp_server_sockets(10001)'
[#<Socket:fd 7>, #<Socket:fd 8>]
```



----------------------------------------
Bug #10203: TCPServer.new has strange behaviour when EADDRINUSE without specifying hostname
https://bugs.ruby-lang.org/issues/10203#change-49403

* Author: Lucas Nussbaum
* Status: Feedback
* Priority: Normal
* Assignee: 
* Category: 
* Target version: 
* ruby -v: ruby 2.1.2p95
* Backport: 2.0.0: UNKNOWN, 2.1: UNKNOWN
----------------------------------------
after:
irb(main):003:0> TCPServer::new(10001)
=> #<TCPServer:fd 9>
I get irb listening to port 10001 using IPv4, but not IPv6:
tcp        0      0 0.0.0.0:10001           0.0.0.0:* LISTEN      1000       376068      24437/irb

a second creation also works, but only binds the IPv6 address:
irb(main):004:0> TCPServer::new(10001)
=> #<TCPServer:fd 10>
tcp6       0      0 :::10001                :::* LISTEN      1000       376098      24437/irb

=> I would have expected the first creation to bind to both IPv4 and IPv6, not just IPv4, and the second attempt to fail.

Trying once again, the creation fails with a strange exception:
irb(main):007:0> TCPServer::new(10001)
TypeError: no implicit conversion of nil into String
	from (irb):7:in `initialize'
	from (irb):7:in `new'
	from (irb):7
	from /usr/bin/irb:11:in `<main>'


Binding explicitely to 0.0.0.0 avoids this:
irb(main):005:0> TCPServer::new('0.0.0.0', 10002)
=> #<TCPServer:fd 11>
irb(main):006:0> TCPServer::new('0.0.0.0', 10002)
Errno::EADDRINUSE: Address already in use - bind(2) for "0.0.0.0" port 10002
	from (irb):6:in `initialize'
	from (irb):6:in `new'
	from (irb):6
	from /usr/bin/irb:11:in `<main>'



-- 
https://bugs.ruby-lang.org/