javasocketsserversocketwifip2p

How to make the client wait for the server socket connection?


I am using wifi direct to communicate between two mobile devices. I have setup sockets to send and receive messages. Everything works fine if I start the server device first(owner) and then the client device(member). I want to start any device in any order and still manage to send messages.

Currently, client waits for 5 secs and if no connection is available, then it stops looking for the server. I want the client to continue looking for the server even after time out till it finds the server connection. I have tried doing this and I am not successful yet in implementing this.

Initial client code:

@Override
    public void run() {
        Socket socket = new Socket();
        try {
            socket.bind(null);
            socket.connect(new InetSocketAddress(address.getHostAddress(), SERVER_PORT), TIME_OUT);
            socketCreator = new SocketCreator(socket, handler);
            new Thread(socketCreator).start();
        } catch (IOException e) {
            e.printStackTrace();
            try {
                socket.close();
            } catch (IOException e1) {
                e1.printStackTrace();
            }
            return;
        }
    }

Modified like this:

 @Override
    public void run() {
        Socket socket = new Socket();
        try {
            socket.setReuseAddress(true);
            socket.bind(null);
            while(!connectedToServer) {
                try {
                    socket.connect(new InetSocketAddress(address.getHostAddress(), SERVER_PORT),
                            TIME_OUT);
                    socketCreator = new SocketReadWriter(socket, handler);
                    new Thread(socketCreator).start();
                    connectedToServer = true;
                } catch (ConnectException e) {
                    Log.i(TAG,"Error while connecting. " + e.getMessage());
                    try {
                        Thread.sleep(2000);
                    } catch (InterruptedException e1) {
                        e1.printStackTrace();
                    }
                } catch (Exception e){
                    Log.i(TAG,"Exception "+e.getMessage());
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
            try {
                socket.close();
            } catch (IOException e1) {
                e1.printStackTrace();
            }
        }
    }

What is missing in my code? How can I make it work?

I am getting this error continuously:

Exception java.io.IOException: fcntl failed: EBADF (Bad file number)

Solution

  • You have to create a new Socket() every time. Failing to connect to the remote server invalidates the socket for any further use.

    If connect() fails, consider the state of the socket as unspecified. Portable applications should close the socket and create a new one for reconnecting. http://man7.org/linux/man-pages/man2/connect.2.html

    Since you are running this on Android - I guess you are not seeing the "Socket closed" error when trying to call connect twice.

    @Override
    public void run()
    {
        connector: while (true)
        {
            Socket socket = new Socket();
    
            try
            {
                socket.connect(new InetSocketAddress("0.0.0.0", 9999), 2000);
                this.doSomethingElseWithConnectedSocket(socket);
                break connector; // break out of the while loop
            }
            catch (ConnectException e)
            {
                // ignore because worthless
            }
    
            try
            {
                 socket.close();
            }
            catch(Throwable x)
            {
                 // ignore
            }
    
            System.out.println("Unable to connect to server ");
    
            try
            {
                Thread.sleep(1000);
            }
            catch (InterruptedException e1)
            {
                // ignore
            }
        }
    }
    
    public void doSomethingElseWithConnectedSocket(Socket value)
    {
         value.close(); // close for no good reason
    }