簡體   English   中英

Java套接字問題:消息只能一次傳遞

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

最近,我正在嘗試一項練習,該練習要求基於tcp套接字設計具有兩個客戶端的服務器。 連接后,SenderClient應該將用戶鍵入的消息發送到Server,然后Server應該將該消息轉發到ReceiverClient。 它像是:

SenderClient->服務器-> ReceiverClient

僅當用戶在發件人中鍵入“退出”時,所有程序才會被終止,否則它們始終在偵聽消息。

現在,我遇到了一個問題:當我在Eclipse Luna中運行這三個程序時,我發現消息只能從SenderClient-> Server-> 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

Socket receiverSocket = serverSocket.accept();

ServerSocketaccept()方法是一項阻止操作:它等待傳入的連接,直到此代碼運行的線程等待。 第一次正確執行循環,因為您有兩個客戶端連接到服務器。 第二次執行循環時,您等待另一個傳入的客戶端。 一種解決方案是通過實現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來處理該連接,然后繼續接受新的傳入連接:

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();
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM