Search code examples
javaandroidsocketsadbserversocket

Why does this ServerSocket in Andorid (attached to PC via USB/ADB) accept connections only once?


Situation: An Android phone has been connected to a PC via USB. Using the ADB command adb forward tcp:35000 tcp:30000, I succeed in forwarding a port.
I want the PC to send its system time to the Android phone every 5 seconds for an hour. To this end, I do the socket programming.

The PC side as a client: (I ignore the exception handling code.)

public void sendTime()
{
    class SendTask implements Runnable
    {
        public void run()
        {
            // Here: I store the host_socket in a member field which is: 
            // Socket host_socket = new Socket("localhost", 35000);
            ObjectOutputStream oos = new ObjectOutputStream(this.host_socket.getOutputStream()); 
            oos.writeObject(msg);
            oos.flush();
        }
    }
    // Here: private Executor exec = Executors.newCachedThreadPool();
    this.exec.execute(new SendTask());
}

The Android phone side as server:

public void getReadyForSync()
{
    ServerSocket server_socket = new ServerSocket();
    server_socket.bind(new InetSocketAddress("localhost", 30000));

    while (true)
    {
        final Socket client_socket = server_socket.accept();
        Runnable receive_task = new Runnable()
        {
            public void run()
            {
                ObjectInputStream ois = new ObjectInputStream(client_socket.getInputStream());
                Message msg = (Message) ois.readObject();
                SyncTimeFragment.this.onReceive(msg);
            }
        }; 
        // Here: private static final Executor exec = Executors.newCachedThreadPool();
        exec.execute(receive_task);
    }
}

In addition, the ServerSocket is established in a separate thread from the main Android thread using AsyncTask and new ServerTask().execute():

public class ServerTask extends AsyncTask<String, Void, Void>
{
    protected Void doInBackground(String... params)
    {
        getReadyForSync();
        return null;
    }
}

Problems:

In my test, the server socket in Android phone accepts connections from PC only once.

Specifically, some debug information is as follows:

(1) Each time (every 5 seconds) sendTime() is called, the host_socket reads:
Socket[addr=localhost/127.0.0.1,port=35000,localport=56520]

Notice: The localport(s) here are the same for all sendTime() calls in a single execution, but different across executions. (I am not sure whether this information is important or not.)

(2) The server_socket reads:
Socket[addr=localhost/127.0.0.1,port=0,localport=30000]

(3) The client_socket received (only once) by the server_socket reads:
Socket[addr=/127.0.0.1,port=43890,localport=30000]


Solution

  • After creating receive_task the code returns to final Socket client_socket = server_socket.accept(); So the server throws away the connection as the run() will only grab one message. You would have to made a while loop in run() too.