我正在创建一个多线程聊天服务器,它应该为每个连接的客户端创建一个单独的线程。每次客户端连接时,我的服务器都会创建一个客户端处理程序类的新实例,该实例应该跟踪来自/到该特定客户端的输入和传出消息。
客户端第一次连接到我的echo服务器时,服务器将响应客户端响应的回显。但是,如果我尝试第二次向服务器发送消息,则客户端会创建IOException。我自己创建了客户端应用程序,但我知道它有效,因为我可以很好地与其他服务器通信。我很确定问题是在这个客户端处理程序类的run方法中的某个地方,但我无法弄清楚它为什么不起作用。这是我的客户端处理程序类中的run方法:
public void run() {
try (
BufferedReader in =
new BufferedReader(
new InputStreamReader(clientSocket.getInputStream()));
PrintWriter out =
new PrintWriter(clientSocket.getOutputStream());
) {
long time = System.currentTimeMillis();
out.println("Server - " + time + ": " + in.readLine());
out.close();
try {
in.close();
} catch (IOException e) {
System.err.println("Couldn't close input stream");
}
} catch(IOException e) {
System.err.println("Got an IOException error while reading or writing from/to client");
}
}
我猜想我应该在某个地方有某种while循环,但是我实现这一切的所有尝试都失败了。例如。我试图更改此代码:
long time = System.currentTimeMillis();
out.println("Server - " + time + ": " + in.readLine());
对此:
String inputLine;
while((inputLine = in.readLine()) != null) {
long time = System.currentTimeMillis();
out.println("Server - " + time + ": " + inputLine);
}
这个解决方案或多或少是oracle网站(http://docs.oracle.com/javase/tutorial/networking/sockets/clientServer.html)表示它应该如何完成的副本。
我认为主要问题可能是我并没有真正掌握服务器/客户端通信的整体概念,因此非常感谢正确推动。
提前致谢!
答案 0 :(得分:0)
您提到的Oracle文章中的重要部分是标题为“支持多个客户端”的部分。
基本的Java套接字API是一个阻塞API,它基本上意味着您调用一个方法,该方法会阻塞,直到发生IO事件。如果您需要等待多个IO事件 - 在您的情况下是传入的客户端连接和传入的数据 - 您必须创建多个线程。
本文中显示的服务器只接受单个incomming(客户端)连接,并在客户端关闭后关闭,因为服务器上的InputStream
将返回null
,导致循环终止。
首先,您的服务器需要看起来像这样(简化示例):
try (ServerSocket serverSocket = new ServerSocket(portNumber))
{
while (running)
{
Socket clientSocket = serverSocket.accept();
new Thread(new ClientHandler(clientSocket)).start();
}
}
注意:为每个客户端连接启动一个线程证明了这一点,但是在管理服务器上的连接负载方面有很大的简化。
客户端代码可以保持原样。
正如我所指出的那样,基础知识将线程管理留给了开发人员 - 这通常会导致麻烦,因为人们只是弄错了。由于这个Java的套接字API已经扩展到创建NIO API - Jakob Jenkov写了一些好tutorials。