Java TCP Echo Server - 广播

时间:2015-01-13 16:50:17

标签: java tcp server

我有一个简单的echo服务器,我希望当一个连接的用户向服务器输入任何内容时,所有其他客户端和该客户端将收到消息+“| MOD”。

它现在不会发送给所有客户,但它应该,我只是不知道我的代码有什么问题,所以现在它只会发送消息+“| MOD”给发送消息的客户端但不是全部其他人也应如此。

我只是不明白,我有一个遍历所有客户端的循环,但它仍然不会发送给所有客户端。

SERVER:

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

请帮忙。

非常感谢。

2 个答案:

答案 0 :(得分:2)

您遇到的一个问题是,每个客户都会无限期地重复read stdin, write socket, read socket, write stdout, ...

当您广播所有其他时,客户端通常仍处于read stdin阶段,因此他们不知道有什么东西等待在套接字上读取。他们还在等待用户输入内容。

最简单的选择之一是在每个客户端中启动两个线程 - 一个只处理read stdin, write socket, ...而另一个处理read socket, write stdout

[另一个(可能更复杂)选项我们使用Java NIO同时轮询套接字和stdin以获取可用输入 ]。

第二个问题是你在服务器的accept调用中阻塞,然后依次从每个套接字中读取。您可以在一个线程中accept,并从客户端读取另一个每个客户端,并重新广播给其他人。 NIO在这里也是一个不错的选择 - 您可以轮询读取任何任何客户端。

答案 1 :(得分:0)

我不完全确定ArrayLists如何使用套接字,所以我肯定会回到使用普通数组(请参阅此处编辑的代码Java EchoTCPServer - Send to all clients

我认为我认为有些事情可以解决:

在客户端:

- 在While循环中停止关闭套接字。在while循环外面关闭它(当客户端完成服务器时)。另外,在Loop之外声明套接字。

请注意:当客户端使用套接字连接到服务器时,会自动为其提供设备端口,因此两个不同的设备永远不会将相同的IP连接到服务器。 TCP连接由2个端口,服务器套接字和客户端套接字组成,套接字由[deviceip:port,serverip:port](iirc)表示。

- 此外,在客户端上,每次进入while循环时都不需要声明新的阅读器。把它全部放在外面。 while循环中唯一的内容应该是readline + print语句。

-readLine是一种阻止方法。 (以防万一你不知道这意味着什么,这意味着readLine会让你的程序被卡在那里直到它实际读取一行。为了绕过它,你可以使用if语句和{{1准备好的功能检查是否有任何内容&#34;读入&#34;,所以如果没有输入它就不会被卡在&#34; readLine&#34;。< / p>

在服务器上:

- 就像我之前说过的那样,我将改回使用普通阵列。

- 您的服务器仍会卡在.accept()上。因此,除了每次连接后一次,您将永远无法读取客户端的输入。您可以使用线程来收听,它仍然有效。

例如:(此代码附带我附加的链接中的代码(也是您的问题),将其放在服务器的while循环之前)

.ready()