2016-02-17 4 views
0

я делаю простой эхо-чат и сервер, но методы send и receive в классе Connection не работают с ObjectInputStream и ObjectOutputStream, но с PrintWriter и BufferedReader работают отлично.Простой чат-клиент и чат сервер

Теперь я пытаюсь понять сериализации с помощью сокетов, помогите мне понять, почему этот код не работает:

Client

public class Client { 
    private Connection connection; 

    private String getServerAddress() { 
     return "localhost"; 
    } 

    private int getServerPort() { 
     return 4444; 
    } 

    public void run() { 
     BufferedReader bis = new BufferedReader(new InputStreamReader(System.in)); 

     try { 
      connection = new Connection(new Socket(getServerAddress(), getServerPort())); 

      SocketThread socketThread = new SocketThread(); 
      socketThread.setDaemon(true); 
      socketThread.start(); 

      while (true) { 
       String text = bis.readLine(); 
       if (text.equalsIgnoreCase("exit")) 
        break; 
       connection.send(text); 
      } 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 

    public static void main(String[] args) { 
     Client client = new Client(); 
     client.run(); 
    } 

    public class SocketThread extends Thread { 
     @Override 
     public void run() { 
      try { 
       while (true) { 
        String message = connection.receive(); 
        System.out.println(message); 
       } 

      } catch (Exception e) { 
       e.printStackTrace(); 
      } 
     } 
    } 
} 

Подключение

public class Connection implements Closeable { 
    private final Socket socket; 
    private final ObjectInputStream in; 
    private final ObjectOutputStream out; 

    public Connection(Socket socket) throws Exception { 
     this.socket = socket; 
     this.in = new ObjectInputStream(socket.getInputStream()); 
     this.out = new ObjectOutputStream(socket.getOutputStream()); 
    } 

    public void send(String message) throws Exception { 
     out.writeObject(message); 
    } 

    public String receive() throws Exception { 
     return (String) in.readObject(); 
    } 

    @Override 
    public void close() throws IOException { 
     in.close(); 
     out.close(); 
     socket.close(); 
    } 
} 

Сервер

public class Server { 

    public static void main(String[] args) { 
     int port = 4444; 

     try (ServerSocket serverSocket = new ServerSocket(port)) { 
      while (true) { 
       Socket socket = serverSocket.accept(); 
       new Handler(socket).start(); 
      } 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 

    private static class Handler extends Thread { 
     private Socket socket; 

     public Handler(Socket socket) { 
      this.socket = socket; 
     } 

     @Override 
     public void run() { 
      try (Connection connection = new Connection(socket)) { 
       while (true) { 
        String message = connection.receive(); 

        if (message.equals("exit")) 
         break; 

        System.out.println(message); 

        connection.send("Echo: " + message); 
       } 
      } catch (Exception e) { 
      } 
     } 
    } 
} 
+3

Пожалуйста, напишите, что вы пробовали, и сообщение об ошибке, которое вы получили. –

+0

У меня нет сообщения об ошибке. Я пытаюсь использовать синхронизированный блок в методах «отправлять» и «получать» для ObjectInputStream и ObjectOutputStream, но сервер не возвращает эхо-сообщение клиенту. Но с PrintWritter и BufferedReader он работает. – Evgeniy

+0

Попробуйте изменить порядок 'this.in = new ObjectInputStream (socket.getInputStream()); this.out = new ObjectOutputStream (socket.getOutputStream()); 'в вашем' Connection'. Также вы можете захотеть 'out.flush()' каждый раз, когда вы что-то отправляете (я не уверен, что он автоматически сбрасывается, что может вызвать ожидание до тех пор, пока использованный буфер не будет заполнен). – Pshemo

ответ

0

Это потому, что ObjectInputStream блок пытаются прочитать заголовок потока, написанный ObjectOutputStream в его конструкторе, и вы создаете оба ваши входные потоки до выходных потоков. Проблему можно решить путем переключения порядка, который вы создаете объект потоков в:

this.out = new ObjectOutputStream(socket.getOutputStream()); 
    this.in = new ObjectInputStream(socket.getInputStream()); 

javadoc for the ObjectOutputStream constructor также отмечает, что вы можете очистить поток после его создания, чтобы обеспечить заголовок передается.

+0

Спасибо за ответ! – Evgeniy

Смежные вопросы