优雅地终止套接字线程

时间:2012-02-27 02:04:58

标签: java sockets exception-handling

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

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

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

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

第一个错误是由implements Runnable引起的。第二个我不确定虽然java.io.*是导入的,所以我不确定它为什么抱怨。

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

1 个答案:

答案 0 :(得分:4)

一般来说,您不会关闭服务器,因为客户说再见。这意味着任何用户都可以连接到您的服务器,无需您的控制即可远程关闭关闭服务器由服务器的管理员或所有者处理,通常通过经过身份验证的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,只需关闭。

注意我没有继承Thread。相反,我实现了一个Runnable,如果你想创建一个线程池或更高级的东西,它将在未来为你提供更大的灵活性。