Java套接字问题:消息只能传递一次

时间:2015-09-27 12:01:34

标签: java sockets tcp

最近我正在尝试一项需要根据tcp套接字设计具有TWO客户端的服务器的练习。连接后,SenderClient应该将用户键入的消息发送到服务器,然后服务器应该将该消息转发给ReceiverClient。它就像:

  

SenderClient - >服务器 - > ReceiverClient

只有当用户在发件人中键入“退出”时,所有程序才会被终止,否则他们总是在监听邮件。

现在我遇到了以下问题:当我在Eclipse Luna中运行这三个程序时,我发现消息可以从SenderClient成功传递 - >服务器 - > ReceiverClient只有一次。之后,该消息将在服务器上被阻止。你们也可以在电脑上运行这三个程序,看看这个奇怪的现象。谢谢你,真的需要帮助。

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

1 个答案:

答案 0 :(得分:0)

Socket receiverSocket = serverSocket.accept();

accept()的{​​{1}}方法是阻塞操作:它等待传入连接,直到此代码运行的线程等待。第一次正确执行循环,因为您有两个客户端连接到服务器。第二次循环执行时,您等待另一个传入的客户端。解决方案是通过实现ServerSocket接口来处理单独线程中的消息,该接口是在新启动的线程上运行的代码:

java.lang.Runnable

}

每当服务器获得两个传入连接时,它会激活一个新的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; } } } 来处理连接,然后继续接受新的传入连接:

Thread