morya
morya

Reputation: 855

Socket EADDRINUSE (Address already in use)

I am doing socket programming. I took reference from below link:

http://examples.javacodegeeks.com/android/core/socket-core/android-socket-example/

Below is detail about my issue. I have created Android lib for this ServerThread (my project requirement), and this is used in test app.

Now test app connect to this through lib and do the process. First time it works perfectly fine, but if I closed and reopen it crashed with exception:

"EADDRINUSE (Address already in use)"

Also tried serverSocket.setReuseAddress(true) this but no luck.

My code:

public void run() {
    Socket socket = null;
    try {
        serverSocket = new ServerSocket(SERVER_PORT);
        serverSocket.setReuseAddress(true);

    } catch (IOException e) {
        Log.e(TAG, "exception1= " + e.getMessage());
    }
    while (!Thread.currentThread().isInterrupted()) {
        try {

            socket = serverSocket.accept();
            Log.d(TAG, "server Connected.......!!!!");

            communicationThread = new CommunicationThread(
                    socket);
            commThread = new Thread(communicationThread);
            commThread.start();

        } catch (IOException e) {
            Log.e(TAG, "exception 2=" + e.getMessage());
        }
    }
}

If I call serverSocket.close() I am getting exception 2 as server socket close. Communication thread is same as given in previous link.

Upvotes: 16

Views: 29686

Answers (4)

Marco Aurelio Silva
Marco Aurelio Silva

Reputation: 1534

Try to create the instance of SocketServer outside of the run() method.

protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState)   
    try {
        // create a new instance of an unbound socket first
        serverSocket = new ServerSocket(); 
        } catch (IOException e) {
           e.printStackTrace();
        }
}

Upvotes: 0

AndrewBloom
AndrewBloom

Reputation: 2408

While other answers pointed out the importance of setReuseAddress(true), another problem that could arise is to construct the ServerSocket twice and call bind with the same parameters. For example if you call twice the code run() of the question, serverSocket will be assigned to a new instance of the ServerSocket class, but the old one is still living until garbage collected. Now constructing with the port value as parameter equals to bind the ServerSocket object, and you are going to end up with two ServerSocket bound to the same address, which is forbidden hence the exception. So build your serverSocket with your chosen port only once!

Upvotes: 5

Remy Lebeau
Remy Lebeau

Reputation: 596592

You have to call setReuseAddress(true) before the socket is bound to the port. You are calling it after, because you are passing the port to the constructor, which will bind the socket immediately.

Try this instead:

serverSocket = new ServerSocket(); // <-- create an unbound socket first
serverSocket.setReuseAddress(true);
serverSocket.bind(new InetSocketAddress(SERVER_PORT)); // <-- now bind it

Upvotes: 33

Gabe Sechan
Gabe Sechan

Reputation: 93614

TCP (and probably some other) sockets can't reuse the same port for a period after closing. This is to prevent confusion if there's data on the network from an existing connection. You can override this behavior, but the default is to wait for a period of time before allowing reuse of the port.

The call to fix this is setReuseAddress(true) on the server socket. But I'm not sure if it needs to be called on the first socket or the second, or both.

Edit:

Here's a blog post describing the TCP socket TIME_WAIT state and why it exists: http://www.serverframework.com/asynchronousevents/2011/01/time-wait-and-its-design-implications-for-protocols-and-scalable-servers.html

Upvotes: 8

Related Questions