2
votes

I am trying to prototype TCP hole punching of a NAT as described in this paper http://www.brynosaurus.com/pub/net/p2pnat/.

I have this simple piece of code that tries to open a connection to a server on a specific local port. I am trying to observe on the public server if the NAT maps both the connections to the same NAT mapping.

int localPort = getFreeLocalPort();

     while (true) {

        Socket connection = new Socket(_publicServerHost,_publicServerPort,
                 getLocalSocketAddress(), localPort);

        connection.setReuseAddress(true);

        connection.close();

     }

The 1st time it connects fine. But the 2nd attempt it throws an exception:

Local port chosen for hole punching: 65416

2012-06-17 15:55:21,545 ERROR - Address already in use: connect

2012-06-17 15:55:25,175 DEBUG - Details: java.net.BindException: Address already in use: connect at java.net.PlainSocketImpl.socketConnect(Native Method) ~[na:1.6.0_24] at java.net.PlainSocketImpl.doConnect(PlainSocketImpl.java:351) ~[na:1.6.0_24] at java.net.PlainSocketImpl.connectToAddress(PlainSocketImpl.java:213) ~[na:1.6.0_24] at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:200) ~[na:1.6.0_24] at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:366) ~[na:1.6.0_24] at java.net.Socket.connect(Socket.java:529) ~[na:1.6.0_24] at java.net.Socket.connect(Socket.java:478) ~[na:1.6.0_24] at java.net.Socket.(Socket.java:375) ~[na:1.6.0_24] at java.net.Socket.(Socket.java:249) ~[na:1.6.0_24]

3

3 Answers

1
votes

try adding connection.setSoLinger(true, 0); directly before connection.close();.

Like so:

connection.setSoLinger(true, 0);
connection.close();

This forces the OS to release the socket.

0
votes

On what basis was the local port chosen? Obviosuly not a sound one. You would be better off letting the system choose it, by specifying zero, and getting the actual value from the socket after opening, if you need it at all.

0
votes

Have you solved your problem ? setReuseAddress() should be called before port is assigned.

Socket connection = new Socket();
connection.setReuseAddress(true);
connection.bind( ...);