Изящно заканчивающаяся резьба - PullRequest
3 голосов
/ 27 февраля 2012

На основании примеров здесь простой клиент сервера сокетов завершит работу при отправке .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();
   }
}

Первая ошибка связана с implements Runnable.Во-вторых, я не уверен, хотя java.io.* импортируется, поэтому я не уверен, почему он жалуется.

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

1 Ответ

4 голосов
/ 27 февраля 2012

Вообще говоря, вы не выключаете сервер, потому что клиент сказал пока.Это означает, что любой пользователь может подключиться к вашему серверу и удаленно отключиться без вашего контроля.Завершение работы сервера выполняется администратором или владельцем сервера, и обычно выполняется путем запуска команды на сервере через сеанс аутентификации 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 вы получите EOFException, когда клиент закроет сокет без отправки «.bye».Таким образом, вы можете перехватить EOFException до IOException и просто завершить работу.

Обратите внимание, что я не создал подкласс Thread.Вместо этого я реализовал Runnable, который дает вам больше гибкости в будущем, если вы захотите создать пул потоков или что-то более изворотливое.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...