java-优雅地终止套接字线程

提问

基于示例here,简单套接字服务器客户端将在发送.bye时终止.下面的代码使用基于线程的方法来接受多个客户端,但不处理正常的处理客户端终止,并且通过重复null会出错.

上述链接中的第一个示例导致客户端和服务器退出.当收到“ .bye”时,下面的服务器代码没有断开连接的规定.我希望客户端正常与服务器断开连接.从客户端收到“ .bye”时,服务器应关闭连接.我认为这需要在System.out.println(streamIn.readUTF())中进行处理;在ChatServerThread中?

已更新问题以反映答案反馈,请参阅历史以获取原始代码:

import java.net.*;
import java.io.*;

public class ChatServerThread implements Runnable
//public class ChatServerThread extends Thread
{  private Socket          socket   = null;
   private ChatServer      server   = null;
   private int             ID       = -1;
   private DataInputStream streamIn =  null;
   private DataOutputStream streamOut = null;

   public ChatServerThread(ChatServer _server, Socket _socket)
   {  server = _server;  socket = _socket;  ID = socket.getPort();
   }
   public void run() {
   try {
       handleClient();
   } catch( EOFException eof ) {
        System.out.println("Client closed the connection.");
   } catch( IOException ioe ) {
        ioe.printStackTrace();
   }
}

   public void handleClient() throws IOException {
      boolean done = false;
      try {
      System.out.println("Server Thread " + ID + " running.");
      while (!done) {
        String nextCommand = streamIn.readUTF();
        if( nextCommand.equals(".bye") ) {
           done = true;
        } else {
           System.out.println( nextCommand );
        }
     }
   } finally {
     streamIn.close();
     streamOut.close();
     socket.close();
   }
   }
   public void open() throws IOException
   {
      streamIn = new DataInputStream(new BufferedInputStream(socket.getInputStre
am()));
      streamOut = new DataOutputStream(new BufferedOutputStream(socket.getOutput
Stream()));
   }
   public void close() throws IOException
   {  if (socket != null)    socket.close();
      if (streamIn != null)  streamIn.close();
      if (streamOut != null) streamOut.close();
   }
}

第一个错误是由于实现了Runnable.第二个我不确定java.io. *是否被导入,所以我不确定为什么会抱怨.

ChatServer.java:34: error: cannot find symbol
         client.start();
               ^
  symbol:   method start()
  location: variable client of type ChatServerThread

最佳答案

一般来说,您不会关闭服务器,因为客户端会说再见.这意味着任何用户都可以连接到您的服务器并在没有您控制的情况下远程关闭.关闭服务器由服务器的管理员或所有者负责,通常是通过经过身份验证的ssh会话在服务器上运行命令来完成的.在unix / linux上,您可以运行:

service chatserver stop

那是如何使它起作用的另一个主题,而只是给您最佳实践的一般概述.现在,如果您想在对话结束时关闭客户端.这更有意义:

public class ChatServerThread implements Runnable {

    .......

    public void run() {
        try {
            handleClient();
        } catch( EOFException eof ) {
            System.out.println("Client closed the connection.");
        } catch( IOException ioe ) {
            ioe.printStacktrace();
        }
    }

    public void handleClient() throws IOException {
       boolean done = false;
       try {
          while(!done) {  
             String nextCommand = streamIn.readUTF();
             if( nextCommand.equals(".bye") ) {
                done = true;
             } else {
                System.out.println( nextCommand );
             }
          }
       } finally {
          streamIn.close();
          streamOut.close();
          socket.close();
       }
    }
}

然后,您可以释放该线程以服务下一个客户端,或者干脆将其关闭.使用DataInputStream,当客户端关闭套接字而不发送“ .bye”时,您将获得EOFException.因此,您可以在IOException之前捕获EOFException,而只需关闭即可.

注意,我没有将线程归为子类.相反,我实现了一个Runnable,如果您想创建线程池或更高级的应用程序,它将在将来为您提供更大的灵活性.

评论