user6441210
user6441210

Reputation:

Java Multi-thread TCP Socket - Receive message from clients until they become disconnected

I have the below code to accept multiple client from my Java Server.

private class SocketServerThread extends Thread {
        int count = 0;
        String error_message = null;
        @Override
        public void run() {
            try{
                serverSocket = new ServerSocket(theSocketServerPORT);
                while (true){
                    final Socket socket = serverSocket.accept();
                    count++;
                    runOnUiThread(new Runnable(){
                        @Override
                        public void run() {
                            Toast.makeText(getApplicationContext(),"New Client with IP: " + socket.getInetAddress() + " and PORT: " + socket.getPort(),Toast.LENGTH_LONG).show();
                        }
                    });
                    SocketServerListenToMessage socketServerListenToMessage = new SocketServerListenToMessage(socket); 
                    socketServerListenToMessage.run();// Start to Receive now
                }
            }catch (IOException e){
                Log.e("IO ERROR",e.toString());
                error_message = "IO ERROR";
            }catch (Exception e){

                Log.e("EX ERROR",e.toString());
                error_message = "EX ERROR";
            }
            if(error_message!=null){
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        Toast.makeText(getApplicationContext(),error_message,Toast.LENGTH_LONG).show();
                    }
                });
            }
        }
    }

Once the client is connected, I call the SocketServerListenToMessage to start listening to client message.

The below code is for SocketServerListenToMessage.

private class SocketServerListenToMessage extends Thread{
        Socket theClientSocket;
        SocketServerListenToMessage(Socket clientSocketListener){
            theClientSocket = clientSocketListener;
            Log.w("SERVER STATUS","Starting to Listen to Clients...");
        }
        @Override
        public void run(){
            try{
                InputStream is = theClientSocket.getInputStream();
                while(true){
                    byte[] lenBytes = new byte[4];
                    is.read(lenBytes, 0, 4);
                    int len = (((lenBytes[3] & 0xff) << 24) | ((lenBytes[2] & 0xff) << 16) |
                           ((lenBytes[1] & 0xff) << 8) | (lenBytes[0] & 0xff));
                    byte[] receivedBytes = new byte[len];
                    is.read(receivedBytes, 0, len);
                    final String received = new String(receivedBytes, 0, len);

                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            Toast.makeText(getApplicationContext(),"Client Says: " + received, Toast.LENGTH_LONG).show();
                            Log.w("Client Says", received);
                        }
                    });
                }
            }catch (IOException e){
                Log.e("IO ERR FROM LISTEN MSG", e.toString());
            }
            catch (Exception e){
                Log.e("EX ERR FROM LISTEN MSG", e.toString());
            }
        }
    }

With the above code, I can connect multiple client. I can also receive the Message from my client. But the problem is I am able to receive a message only from the First Client that is become connected to my Server. The second and soon client was not.

The below code is for my Client to Send Message. Note I am using C# for my client.

IPEndPoint serverAddress;
Socket clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);  //I am using Socket

/*********To Send Message to Server**********/

String toSend = txt_v.Text; //The message came from TextBox.
Task f = Task.Factory.StartNew(() => {
     if (clientSocket.Connected)
     {
       int toSendLen = System.Text.Encoding.ASCII.GetByteCount(toSend);
       byte[] toSendBytes = System.Text.Encoding.ASCII.GetBytes(toSend);
       byte[] toSendLenBytes = System.BitConverter.GetBytes(toSendLen);
       clientSocket.Send(toSendLenBytes);
       clientSocket.Send(toSendBytes);

      }
});

I think the problem is in while loop in SocketServerListenToMessage. I tried to remove the while loop and the Server was able to receive the message from all client but it's only one message per client. I want the Server to listen to client's message until they become disconnected. How can I do that?

Upvotes: 1

Views: 226

Answers (1)

user6441210
user6441210

Reputation:

I just make it work. Thanks to this Link.

If I'm not mistaken, from the link, I am using a singlethreaded. So from my SocketServerThread I have to change

SocketServerListenToMessage socketServerListenToMessage = new SocketServerListenToMessage(socket); 
                    socketServerListenToMessage.run();// Start to Receive now

to

new Thread(new SocketServerListenToMessage(socket)).start();

and change the class SocketServerListenToMessage to

private class SocketServerListenToMessage implements Runnable {
        protected Socket clientSocket = null;

        public SocketServerListenToMessage(Socket clientSocket) {
            this.clientSocket = clientSocket;
        }

        @Override
        public void run() {
            try {
                while (true){
                    InputStream is = clientSocket.getInputStream();
                    byte[] lenBytes = new byte[4];
                    is.read(lenBytes, 0, 4);
                    int len = (((lenBytes[3] & 0xff) << 24) | ((lenBytes[2] & 0xff) << 16) |
                            ((lenBytes[1] & 0xff) << 8) | (lenBytes[0] & 0xff));
                    byte[] receivedBytes = new byte[len];
                    is.read(receivedBytes, 0, len);
                    final String received = new String(receivedBytes, 0, len);

                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            Toast.makeText(getApplicationContext(), "Client Says: " + received, Toast.LENGTH_LONG).show();
                            Log.w("Client Says", received);

                        }
                    });
                }

            } catch (IOException e) {
                Log.e("IO ERR FROM LISTEN MSG", e.toString());
            } catch (Exception e) {
                Log.e("EX ERR FROM LISTEN MSG", e.toString());
            } finally {
                try{
                    clientSocket.close();
                    Log.w("CLIENT DISCONNECTED", "A client is disconnected.");
                }catch (IOException e){
                    Log.w("IO ERR DISCONNECTION", e.toString());
                }
            }
        }
    }

I just need to implement Runnable instead of Thread to make it Multi.

Upvotes: 1

Related Questions