简体   繁体   中英

Java Socket Issue: Message Can Only Be Passed For One Time

recently I am attempting an exercise that requires to design a server with TWO clients based on tcp socket. After connected, the SenderClient should send a message typed by user to Server, and Server should then forward that message to the ReceiverClient. It is like:

SenderClient -> Server -> ReceiverClient

Only when user types "quit" in sender, all the programs will be terminated, otherwise they are always listening for messages.

Now I have met the problem that: when I run that three programs in Eclipse Luna, what I found is that the message can be successfully passed from SenderClient -> Server -> ReceiverClient for only one time. And after that, the message will be blocked at the Server. Can you guys also run those three programs on your computer to see the strange phenomenon. Thank you and really need help here.

import java.io.*;
import java.net.*;

public class Server {

public static void main (String args[]) {

    InputStream is = null;
    InputStreamReader isr = null;
    BufferedReader br = null;
    OutputStream os = null;
    PrintWriter pw = null;

    String info = null;

    try {
        // listening to port
        ServerSocket serverSocket = new ServerSocket(8888);
        System.out.println("Server is listening to port 8888...");
        while (true) {
            // respond to clients
            Socket receiverSocket = serverSocket.accept();
            System.out.println("receiver client connected!");
            Socket senderSocket = serverSocket.accept();
            System.out.println("sender client connected!");
            // get input stream, read messages from sender
            is = senderSocket.getInputStream();
            isr = new InputStreamReader(is);
            br = new BufferedReader(isr);
            info = br.readLine();
            // close all resources when user types "quit"
            if (info.equalsIgnoreCase("quit")) {
                // close resources when user types "quit"
                is.close();
                isr.close();
                br.close();
                os.close();
                pw.close();
                serverSocket.close();
                System.out.println("Server terminated!");
                break;
            }
            // print out the message
            if (info != null) {
                System.out.println("Sender -> Server: " + info);
            }               
            // get output stream, forward messages to receiver          
            os = receiverSocket.getOutputStream();
            pw = new PrintWriter(os);
            pw.println(info);
            pw.flush();
        } // end while
    } catch (IOException e) {
        e.printStackTrace();
    } // end try...catch

} // end main method

} // end class Server


import java.io.*;
import java.net.*;

public class ReceiverClient {

    public static void main (String args[]) {

        InputStream is = null;
        BufferedReader br = null;

        String info = null;

        try {
            while (true) {
                // create receiver socket with host and port number
                Socket receiverSocket = new Socket("localhost", 8888);
                // get input stream, read the information
                is = receiverSocket.getInputStream();
                br = new BufferedReader(new InputStreamReader(is));
                info = br.readLine();
                // close all resources when user types "quit"
                if (info.equalsIgnoreCase("quit")) {
                    is.close();
                    br.close();
                    System.out.println("Receiver client terminated!");
                    break;
                }
                // print out the message
                if (info != null) {
                    System.out.println("Sender -> Server -> Receiver: " + info);
                }
                receiverSocket.close();
            } // end while
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } // end try...catch

    } // end main method

} // end class ReceiverClient

import java.io.*;
import java.net.*;

public class SenderClient {

    public static void main (String args[]) {

        OutputStream os = null;
        PrintWriter pw = null;
        BufferedReader br = null;

        String userInput = null;

        try {
            while (true) {
                // create sender socket with host and port number
                Socket senderSocket = new Socket("localhost", 8888);
                // get message from user input
                System.out.println("Please input a message:");
                br = new BufferedReader(new InputStreamReader(System.in));
                userInput = br.readLine();
                // get output stream, send message to server
                os = senderSocket.getOutputStream();
                pw = new PrintWriter(os);
                pw.println(userInput);
                pw.flush();
                senderSocket.close();
                // close all resources when user types "quit"
                if (userInput.equalsIgnoreCase("quit")) {
                    os.close();
                    pw.close();
                    System.out.println("Sender client terminated!");
                    break;
                }
            } // end while
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } // end try...catch    

    } // end main method

} // end class SenderClient

Socket receiverSocket = serverSocket.accept();

The accept() method of ServerSocket is a blocking operation: it waits for an incoming connection and until then the thread this code runs on waits. The first time the loop is executed correctly because you have the two clients connect to the server. The second time the loop gets executed you wait for another incoming client. A solution for this is to handling of the messages in a separate thread by implementing the java.lang.Runnable interface, which is the code that runs on the newly launched thread:

class ClientConnection implements Runnable{

private Socket sender;
private Socket receiver;

public ClientConnection(Socket sender, Socket receiver){
    this.sender = sender;
    this.receiver = receiver;
}

@Override
public void run(){
    is = sender.getInputStream();
    isr = new InputStreamReader(is);
    br = new BufferedReader(isr);
    OutputStream os = receiver.getOutputStream();
    PrintWriter pw = new PrintWriter(os);

    boolean clientQuit = false;

    while(!clientQuit){
        info = br.readLine();   

        if (info.equalsIgnoreCase("quit")) {
            // close resources when user types "quit"
            is.close();
            isr.close();
            br.close();
            os.close();
            pw.close();
            serverSocket.close();
            System.out.println("Server terminated!");
            clientQuit = true;
        } else{
            pw.println(info);
            pw.flush;
        }
    }
}

}

Whenever the server gets two incoming connections, it fires up a new Thread that will handle the connection and then continues on accepting new incoming connections:

while (true) {
    // respond to clients
    Socket receiverSocket = serverSocket.accept();
    System.out.println("receiver client connected!");
    Socket senderSocket = serverSocket.accept();
    System.out.println("sender client connected!");

    ClientConnection connection = new ClientConnection(senderSocket, receiverSocket);
    Thread connectionThread = new Thread(connection);
    connectionThread.start();
}

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