您希望服务器始终在指定端口上侦听。一旦服务器注意到该端口上的传入连接,您应该创建一个新线程来处理该客户端和服务器之间的通信,而主线程继续侦听其他传入连接。这样,您可以将多个客户端连接到一个服务器。像这样:
private void listen() throws IOException {
serverSocket = new ServerSocket(port)
while (GlobalFlags.listening) {
new ServerThread(serverSocket.accept();
if (GlobalFlags.exit) {
serverSocket.close();
break;
}
}
}
GlobalFlags 是控制监听过程的变量,并不是真正必要的。你可以做一段时间 True ,然后一直听下去。
在我的项目中,我有一个主服务器控制器,它的侦听器在线程中运行。控制器控制 GlobalFlags。我敢肯定,除了使用全局标志之外,还有一种更好的方法来进行线程间通信,但对我来说,这是当时最简单的方法。
ServerThread 应该一直循环在向客户端发送输出和从客户端接收输入之间切换。像这样:
ServerThread(Socket socket) {
super("GameServerThread");
this.socket = socket;
try {
this.socket.setTcpNoDelay(true);
} catch (SocketException e) {
// Error handling
}
this.terminate = false;
}
@Override
public void run() {
try {
out = new PrintWriter(socket.getOutputStream(), true);
in = new BufferedReader(
new InputStreamReader(
socket.getInputStream()));
String inputLine, outputLine;
while ((inputLine = in.readLine()) != null) {
outputLine = processInput(inputLine);
out.println(outputLine);
if (terminate) {
break;
}
}
}
out.close();
in.close();
socket.close();
} catch (Exception e) {
// Error handling, should not use Exception but handle all exceptions by themselves.
}
在客户端,您有一个线程通过类似的循环运行,从服务器接收输入,然后将输出发送到服务器。
在此示例中,processInput 是用于处理客户端输入的函数。如果您希望服务器启动联系,您可以让服务器在侦听输入之前向输出流发送一些内容,并让客户端先侦听。
我已经从我自己的一个项目中提取了这个例子,并且 this.socket.setTcpNoDelay(true) 应该使这个过程更快。参考这里:http ://www.rgagnon.com/javadetails/java-0294.html
“java.net.Socket.setTcpNoDelay() 用于启用/禁用 TCP_NODELAY,该 TCP_NODELAY 禁用/启用 Nagle 算法。Nagle 算法尝试通过最小化发送的段数来节省带宽。当应用程序希望减少网络延迟并提高性能时, 他们可以禁用 Nagle 的算法(即启用 TCP_NODELAY)。数据将更早发送,但会增加带宽消耗。Nagle 的算法在 RFC 896 中有描述。
您可以使用 java.net.Socket.getTcpNoDelay() 获得当前的“TCP_NODELAY”设置”
因此,要将消息发送到特定客户端,您可以在创建时将所有线程放在 ArrayList 中,这样您就可以跟踪所有当前连接的客户端。您可以让 processInput 方法停止并轮询队列/变量,直到另一个类将要发送的消息放入队列/变量中。所以如何获得类的句柄取决于你对 processInput 的实现。您可以给每个线程一个 ID(这是我在我的项目中所做的),并且可能让 processInput 方法在 index=ID 处轮询一个 ArrayList。然后要将输出发送到客户端,您必须将变量设置为 index=ID。
这种方法对我个人来说似乎有点笨拙,但我不确定我该怎么做。您可能会使用队列并让 processInput 将输入写入其队列,然后等待另一个类读取它并将其响应放入队列中。但我个人从未在 java 中使用过队列,所以你应该自己阅读。