Search code examples
javaandroidsocketstcphole-punching

Java(Android): create ServerSocket on LocalPort used for another Socket


I'm a little stumped and probably because I don't know how to search for this properly (I've tried many different keywords). Anyway, I'm attempting a variation of TCP hole punching(with a rendezvous server). I have created a TCP socket to the server and closed it without throwing any exceptions. But when I attempt to create a ServerSocket on the localport of the original socket it fails with IOException.

private static int LOCALPORT = 0;
private static String TARGETIP = "88.888.88.888";
private static int TARGETPORT = 8888;
try{
    InetAddress serverAddr = InetAddress.getByName(TARGETIP);
    socket = new Socket(serverAddr, TARGETPORT);
    LOCALPORT = socket.getLocalPort();
    socket.close();
    ServerSocket sSocket = new ServerSocket(LOCALPORT);
    Socket skt = sSocket.accept();
}
catch (IOException e){
}

I just cannot wrap my head around why I cannot close the socket and open a serversocket on the same port.

UPDATE: from logcat

java.net.BindException: bind failed: EADDRINUSE (Address already in use)
Caused by: libcore.io.ErrnoException: bind failed: EADDRINUSE (Address already in use)

Solution

  • I believe I have solved my own problem thanks to greenapps and some additional searching online. Instead of closing the original socket, you need to set it to reuse instead! So simple, wow.

    private static int LOCALPORT = 0;
    private static String TARGETIP = "88.888.88.888";
    private static int TARGETPORT = 8888;
    try{
        InetAddress serverAddr = InetAddress.getByName(TARGETIP);
        socket = new Socket(serverAddr, TARGETPORT);
        LOCALPORT = socket.getLocalPort();
        //socket.close();
        socket.setReuseAddress(true);
        ServerSocket sSocket = new ServerSocket(LOCALPORT);
        Socket skt = sSocket.accept();
        sSocket.close();
    }
    catch (IOException e){
        e.getMessage();
        e.printStackTrace();
    }