简体   繁体   中英

Java Socket client/server pair can only send one message at a time

A successful conversation can be carried out between the client and the server. However this is only if one message is sent between the client and server.

Example (Works):

Client: Hello
Server: helloo
Client: what time is it
Server: Let me get that for you

Example (Does not work):

Client: Hello
Server: helloo
Server: *How are you today*
Server: *test message*
Client: Yes

The messages between the asterisks do not appear on the client side untill the client sends 2 messages. From what I understand it seems to work like a net-message system where the number of messages sent by the server has to equal n+-1 the number of messages sent by the client, for all the messages to be shown.

Client Side Code:

try {
            Socket client_socket= new Socket(hostname,port_number);
            PrintWriter output = new PrintWriter(client_socket.getOutputStream(),true);
            BufferedReader input = new BufferedReader(new InputStreamReader(client_socket.getInputStream()));
            BufferedReader stdIn=new BufferedReader(new InputStreamReader(System.in));

            String fromUser,fromServer;
            while ((fromServer=input.readLine())!=null) {
                System.out.println("Server: "+fromServer);
                if (fromServer.equals("Quit")) {
                    break;
                } 
                fromUser=stdIn.readLine();
                if (fromUser!=null) {
                    System.out.println("Client: "+fromUser);
                    output.println(fromUser);
                }

            }

        }

Server Side Code:

try {
            ServerSocket server_socket=new ServerSocket(port_number);
            Socket client_socket= server_socket.accept();
            PrintWriter output = new PrintWriter(client_socket.getOutputStream(),true);
            BufferedReader input = new BufferedReader(new InputStreamReader(client_socket.getInputStream()));
            BufferedReader stdIn=new BufferedReader(new InputStreamReader(System.in));
            output.println("Established");
            String fromUser, fromServer;
            while ((fromUser=input.readLine())!=null) {
                System.out.println("Client: "+fromUser);
                if (fromUser.equals("Quit")) {
                    break;
                } 
                fromServer=stdIn.readLine();
                if (fromServer!=null) {
                    System.out.println("Server: "+fromServer);
                    output.println(fromServer);
                }
            }

        }

Looking at the code I can see why this would happen, its because the SOP after the While loop initialization stops the code waiting for 1 line of input, and then waits to send its own sentence, before receiving another. I tried putting these within the if statements, but this results in no communication at all.

I cant seem to figure out how to fix this.

If this requires threads, is there another way? (i'm not too familiar with threads)

Depending on the nature of your program, i would advise you to use more threads to handle messaging.

Lets start with the server: If the server can have multiple clients, than it probably would be wise to distinguish every client with a thread, for example:

            ServerSocket ss;

            try {
                ss = new ServerSocket(portIn);
                while (true) {
                    Socket s = ss.accept();
                    // Option 1: runnable class
                    new Thread(new CustomRunnableClass(s)).start();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }

Or if you dont want your "session manager" to be a custom runnable class, you can replace the line new Thread(new CustomRunnableClass(s)).start(); with the following

new Thread(new Runnable() {
   @Override
   public void run() {
        new SomeClass().runThisClass();
   }
}

On the client side i would suggest that whatever class that listens to new messages from sockets will be distinguished by a new thread:

private void startListening() {
    new Thread(new Runnable() {
        @Override
        public void run() {
            for(;;) {
                String msg = dis.readUTF();
                System.out.println("  ----- Recieved New Message -----\n" + msg);
                for (IMessageListener listener : listeners) {
                    try {
                        listener.onMessageRecieved(msg);
                    } catch (Exception e) {

                    }
                }
            }
        }
    }).start();
}

this way the client listens to any message received by the client and runs a method to handle them upon receiving, and is not hung in the meanwhile.

Hope this was helpful.

you need non-blocking sockets, the reader function should return intermediately if there is no data in the input buffer.

http://www.java2s.com/Tutorials/Java/Java_Network/0070__Java_Network_Non-Blocking_Socket.htm

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM