0

I'm creating a multithreaded chat server that supposed to create a separate thread for each connected client. Every time a client connects, my server creates a new instance of a client handler class, that is supposed to keep track for ingoing and outgoing messages from/to that specific client.

The first time a client connects to my echo server, the server will respond with an echo of the clients response. But if I try to send a message to the server a second time, the client creates an IOException. I have the created the client application myself, but I know it works because I can communicate with other servers just fine. I'm pretty sure the problem is somewhere in the run method of this client handler class, but I can't figure out why it's not working. Here's the run method in my client handler class:

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

I've guessed that I'm supposed to have some kind of while loop somewhere, but all of my attempts to implement this have failed. E.g. I've tried to change this code:

long time = System.currentTimeMillis();         
out.println("Server - " + time + ": " + in.readLine());

To this:

String inputLine;
while((inputLine = in.readLine()) != null) {
    long time = System.currentTimeMillis();         
    out.println("Server - " + time + ": " + inputLine);
}

This solution is more or less a copy of how the oracle site (http://docs.oracle.com/javase/tutorial/networking/sockets/clientServer.html) says it's supposed to be done.

I think the main problem might be me not really grasping the whole concept of server/client communication, so a push in the right direction would be greatly appreciated.

Thanks in advance!

4

1 回答 1

0

您提到的 Oracle 文章中的重要部分是标题为 - Supporting Multiple Clients的部分。

基本的 Java 套接字 API 是一个阻塞 API,这基本上意味着您调用一个方法并且该方法阻塞,直到发生 IO 事件。如果您需要等待多个 IO 事件 - 在您的情况下是传入客户端连接和传入数据 - 您必须创建多个线程。

文章中显示的服务器只接受单个传入(客户端)连接,并且一旦客户端关闭就会关闭,因为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 编写了一些很好的教程

Netty也值得一看,我个人认为它比NIO更容易使用。

于 2014-09-24T08:18:34.103 回答