我有一个简单的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();
}
}
}
请帮忙。
非常感谢。
答案 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()