簡體   English   中英

Java TCP Echo Server-廣播

[英]Java TCP Echo Server - Broadcast

我有一個簡單的回顯服務器,我希望當連接的用戶在服務器上鍵入任何內容時,所有其他客戶端和該客戶端都將收到一條消息+“ | MOD”。

它現在不會發送給所有客戶端,但是它應該並且我只是不知道我的代碼出了什么問題,所以現在它將只發送消息+“ | MOD”給發送了消息的客戶端,而不發送給所有其他用戶。這應該。

我只是不明白,我有一個遍歷所有客戶端的循環,但是仍然不會發送給所有人。

服務器:

package com.murplyx.server;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;

public class Server {
    public static ServerSocket server;
    public static ArrayList<Socket> clients = new ArrayList<Socket>();

    public static void broadcast(String message) {
        try {
            for (Socket socket : clients) {
                PrintWriter out = new PrintWriter(socket.getOutputStream(), true);

                out.println(message);
            }
        } catch(Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String args[]) {
        try {
            server = new ServerSocket(9000);

            while (true) {
                clients.add(server.accept());

                for (Socket socket : clients) {
                    BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));

                    String line = in.readLine();

                    if (line != null) {
                        broadcast(line + " | MOD");
                    }
                }
            }
        } catch(Exception e) {
            e.printStackTrace();
        }
    }
}

客戶:

package com.murplyx.client;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;

public class Client {
    public static void main(String args[]) {
        try {
            while (true) {
                Socket socket = new Socket("localhost", 9000);

                BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                PrintWriter out = new PrintWriter(socket.getOutputStream(), true);

                BufferedReader input = new BufferedReader(new InputStreamReader(System.in));

                out.println(input.readLine());

                System.out.println(in.readLine());

                socket.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

請幫忙。

非常感謝。

您遇到的問題之一是,每個客戶端都會反復read stdin, write socket, read socket, write stdout, ...無限。

當廣播時,所有其他客戶端通常仍處於read stdin階段,因此他們不知道套接字上有等待讀取的內容。 他們仍在等待用戶輸入內容。

最簡單的選擇之一是在每個客戶端中啟動兩個線程-一個僅處理read stdin, write socket, ... ,另一個處理read socket, write stdout

[另一個(可能更復雜)選項,我們可以使用Java NIO 同時 輪詢兩種插座和標准輸入可用的輸入。

第二個問題是,你堵在accept服務器的呼叫,然后從每個插座依次閱讀。 您可能會accept一個線程,並讓每個客戶端僅從該客戶讀取另一個線程,然后重新廣播到其他線程。 NIO也是一個不錯的選擇-您可以輪詢任何客戶端的讀取。

我不確定ArrayLists如何與套接字一起玩,所以我肯定會回過頭來使用普通的數組(請參閱此處的編輯代碼Java EchoTCPServer-發送給所有客戶端

我認為可以解決的一些問題:

在客戶端上:

-停止在While循環中關閉套接字。 在while循環外關閉它(當客戶端用服務器完成時)。 另外,在循環外聲明套接字。

關於此提示 :客戶端建立套接字以連接到服務器時,會自動為它提供設備端口,因此兩個不同的設備永遠不會將相同的IP連接到服務器。 TCP連接由服務器套接字和客戶端套接字兩個端口組成,並且套接字由[deviceip:port,serverip:port](iirc)表示。

-此外,在客戶端上,您無需每次通過while循環時都聲明新的閱讀器。 放在外面。 while循環中唯一的東西應該是您的readline + print語句。

-readLine是一種阻止方法。 (以防萬一,您不知道這意味着什么,這意味着readLine將使程序停留在該位置,直到它實際讀取一行為止。要繞過該行,可以將if語句與.ready()函數結合使用准備函數檢查是否有任何內容要“讀入”,因此,如果沒有輸入,則不會卡在“ readLine”上。

在服務器上:

-和我之前說的一樣,我將改回使用普通數組。

-您的服務器仍將卡在.accept()上。 這樣,您將永遠無法讀取來自客戶端的輸入,除非在每次連接之后都執行一次。 您可以改用線程監聽,它仍然可以正常工作。

例如:(此代碼與我附加的鏈接(也是您的問題)中的代碼一起,將其放在服務器的while循環之前)

// create a tcp listener thread to deal with listening to clients
Thread listenerThread = new Thread() {
    public void run() {
        String clientSentence;

        while (true) {
            //loop through each connected socket    
            for (int i = 0; i <= intLastSocket; i++) {
                Socket z = clientSocket[i];
                //make sure the socket is not null or closed (can't do anything 
                //with closed or null sockets           
                if ((z != null) && (!z.isClosed())) {
                    try {
                        // Deal with TCP input here
                        BufferedReader input = new BufferedReader(new 
                           InputStreamReader(z.getInputStream()));
                        // read in a line but only if there is one
                        if (input.ready()) {
                            clientSentence = input.readLine();
                        }
                    } catch (IOException x) {
                        printTCP("IOException caught when reading in: "
                                + x.toString());
                    }
                    if (clientSentence != null) {
                        System.out.println("Received from client: "
                                + clientSentence);
                        //send this message to the client
                        outputStream[i].println(clientSentence + " | MOD");
                    }

                    // clear the input
                    clientSentence = null;
                }
            }
        }
    }
};
listenerThread.start();

暫無
暫無

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

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