Java TCP回送服务器-广播
我有一个简单的echo服务器,我希望当连接的用户在服务器上键入任何内容时,所有其他客户端和该客户端都会收到一条消息+“|MOD” 它现在不会发送给所有客户,但它应该发送,我只是不知道我的代码中有什么错误,所以现在它只会将消息+“| MOD”发送给发送消息的客户,但不会发送给所有其他客户 我只是不明白,我有一个循环,通过所有客户端,但它仍然不会发送到所有客户端 服务器:Java TCP回送服务器-广播,java,tcp,server,Java,Tcp,Server,我有一个简单的echo服务器,我希望当连接的用户在服务器上键入任何内容时,所有其他客户端和该客户端都会收到一条消息+“|MOD” 它现在不会发送给所有客户,但它应该发送,我只是不知道我的代码中有什么错误,所以现在它只会将消息+“| MOD”发送给发送消息的客户,但不会发送给所有其他客户 我只是不明白,我有一个循环,通过所有客户端,但它仍然不会发送到所有客户端 服务器: package com.murplyx.server; import java.io.BufferedReader; impo
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();
}
}
}
请帮忙
非常感谢。您遇到的一个问题是,每个客户端都会无限重复地执行
读取标准输入、写入套接字、读取套接字、写入标准输出等操作
当您广播时,所有其他客户端通常仍处于read stdin
阶段,因此它们不知道套接字上有等待读取的内容。他们仍在等待用户输入内容
最简单的选择之一是在每个客户机中启动两个线程-一个只处理读取标准输入,写入标准输出,
,另一个处理读取标准输入,写入标准输出
[另一个(可能更复杂的)选项是使用Java NIO同时轮询套接字和stdin以获取可用输入]
第二个问题是,您正在服务器中阻塞accept
调用,然后依次读取每个套接字。您可以在一个线程中接受
,并让每个客户机只从该客户机读取另一个线程,然后重新广播给其他客户机。NIO在这里也是一个很好的选择-您可以轮询任何客户端的读取。我不确定ArrayList如何使用套接字,因此我肯定会使用普通数组(请参阅此处编辑的代码)
有些我认为可以解决的问题:
在客户机上:
-停止关闭While循环中的套接字。在while循环之外关闭它(当客户端与服务器完成连接时)。另外,在循环外部声明套接字
注意这一点:当客户端使用套接字连接到服务器时,会自动为其提供一个设备端口,因此两个不同的设备将永远不会有相同的IP连接到服务器。TCP连接由两个端口组成:服务器套接字和客户端套接字,这些套接字由[deviceip:port,serverip:port](iirc)表示
-此外,在客户端上,不需要每次通过while循环时都声明一个新的读卡器。把这些都放在外面。while循环中的唯一内容应该是readline+print语句
-readLine是一种阻塞方法。(以防您不知道这意味着什么,这意味着readLine将使您的程序卡在那里,直到它实际读取一行为止。要绕过这一点,您可以使用if语句与.ready()
函数组合使用。ready函数检查是否有任何内容需要“读入”,因此,如果没有输入,它就不会卡在“readLine”上
在服务器上:
-就像我前面说的,我会改回使用普通数组
-您的服务器仍将卡在.accept()上。因此,您将永远无法从客户端读取输入,除非每次连接后读取一次。您可以使用线程来侦听,它仍然可以工作
例如:(此代码与我附加的链接(也是您的问题)中的代码一致,将其放在服务器的while循环之前)
//创建一个tcp侦听器线程来处理侦听客户端
线程列表线程=新线程(){
公开募捐{
字符串介词句;
while(true){
//通过每个连接的插座循环
对于(int i=0;i InServer.broadcast()
。如果我没记错的话,关闭PrintWriter将关闭底层套接字;如果您需要多次广播,我不会关闭它。@Fildor那也是-我还没有发现。请在代码中显示出来好吗?我在发布我的问题后想,所有客户端都有相同的IP,因为我测试它们时它们都有。我需要这样做我不知道这些写stdin和stdout是什么,所以当我说读stdin
时,我指的是从系统中读取。在中,我在客户端尝试了这一点,但它只是终止了程序:与普通数组相比,使用数组列表
没有交互作用。@Alnitak你能详细说明一下吗?“我不确定ArrayList是如何使用套接字的”-与使用普通数组的方式完全相同。他的代码中的这一部分可能很好,只是我只使用普通数组处理它,从未尝试实现ArrayList。感谢您的澄清!
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();
}
}
}
// 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();