Java - Программирование сокетов - Как заставить клиента получать сообщения с нескольких серверов?

Мне нужно, чтобы несколько клиентов общались с несколькими серверами и обрабатывали ответы от них.

До сих пор мне удавалось написать серверный код, который привязывается к нескольким клиентам (создает поток для каждого клиента), а клиент подключается к нескольким серверам.

Место, где я столкнулся с проблемой, находится на стороне клиента - я не могу получать ответы от серверов.

Последовательность операций следующая:

Предположим, у меня есть 2 сервера и 1 клиент. клиент подключается к обоим серверам, отправляет им сообщения, оба сервера получают его и оба отправляют ответ клиенту - я не могу получить этот ответ.

Код сервера -

 @Override
  public void run() {
    try {

      // create a serversocket to listen to requests
      ServerSocket serverSocket = new ServerSocket(port);

      // create n sockets to listen to 5 client
      for (int i = 0; i < n; i++) {
        Socket socket = serverSocket.accept();
        // create a processor thread for each to read and process the incoming Messages
        Processor processor = new Processor(socket);
        processor.start();
      }

     serverSocket.close();
    } catch (IOException e) {
      e.printStackTrace();
    }

Процессор в коде сервера -

@Override
  public void run() {
    try {
      ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
      OutputStreamWriter out = new OutputStreamWriter(socket.getOutputStream());

      while (true) {
        String str = in.readObject();

        System.out.println(message);

        out.write("Got your message " + message.toString());

      }
    } catch (IOException e) {
    } catch (ClassNotFoundException e) {
      e.printStackTrace();
    } catch (ClassCastException e) {
      e.printStackTrace();
    } catch (Exception e) {
      e.printStackTrace();
    }

    System.out.println("Processor completed " );
  }

Код клиента -

public static void main(String[] args) throws IOException, InterruptedException {

    // make the connections with other nodes
    connections = connect();

    // connect() creates connections from the client to all servers and stores the socket and out objects in the object called Connections.Code omitted to avoid clutter

    // process all the commands 
    while(!commands.isEmpty()){

      for(int i=0 ; i<2; i++){
      send(commands.poll() , i);

    }

      Thread.sleep(500);
    }

  }


  // Sends Message m to the node i
  public static synchronized void send(Message m, int i) {
    try {
      connections.outs[i].writeInt(m.nodeId);
      connections.outs[i].writeInt(m.timestamp);
      connections.outs[i].writeObject(m.type);
      connections.outs[i].writeObject(m.value);
      connections.outs[i].flush();

      InputStreamReader isr = new       InputStreamReader(connections.sockets[i].getInputStream());
      final BufferedReader br = new BufferedReader(isr);

      new Thread() {
        public void run() {
          try {
            while (true) {
              String message = br.readLine();
              System.out.println("Message received from the server : " +message);
            }
          } catch(IOException e) {
            e.printStackTrace();
          }
        }
      }.start();

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

Я уверен, что делаю что-то не так, когда слушаю сообщение. Любое предложение о том, как получать и обрабатывать сообщения с нескольких серверов, было бы очень полезно.

ТИА


person maddie    schedule 25.03.2017    source источник
comment
Клиент слушает?   -  person Grim    schedule 25.03.2017
comment
Опишите, что происходит при запуске. Сообщения об ошибках? Зависает? Вы пробовали отладчик?   -  person slim    schedule 25.03.2017
comment
@slim Я не согласен с закрытым голосованием и комментарием. Мэдди описывает конкретную проблему, которую могут скомпилировать и отладить члены этой сети. Пожалуйста, будьте осторожны, употребляя слово «ерунда», неиспользуемая переменная — это не чепуха.   -  person Grim    schedule 25.03.2017
comment
@PeterRader он не скомпилируется, если вы не будете много гадать при определении переменных, которые в настоящее время не объявлены. А поломка не описана.   -  person slim    schedule 25.03.2017
comment
@slim А, понятно: connections.out   -  person Grim    schedule 25.03.2017
comment
п, сообщение, команды. И не переменная, а то, что происходит в connect()   -  person slim    schedule 25.03.2017
comment
@slim Хорошо, я частично согласен с закрытым голосованием, потому что ряд членов этой сети могут не иметь возможности отлаживать.   -  person Grim    schedule 25.03.2017
comment
@slim Я удалил много логики кода, которая не имела отношения к моему вопросу, постараюсь сохранить объявление переменной в будущем. Я не взял какой-то код и не отредактировал его в соответствии со своим вариантом использования. Я новичок в программировании потоков и сокетов - может быть, поэтому код не на должном уровне.   -  person maddie    schedule 25.03.2017


Ответы (1)


Я сталкиваюсь с двумя проблемами:

1. Вы не прошились.

out.write("Получил ваше сообщение " + message.toString());

2. На сервер вы не отправляете \n

Проблема в методе readLine

  new Thread() {
    public void run() {
      try {
        while (true) {
          String message = br.readLine();
          System.out.println("Message received from the server : " +message);
        }
      } catch(IOException e) {
        e.printStackTrace();
      }
    }
  }.start();

из документации:

Читает строку текста. Строка считается завершенной переводом строки ('\n'), возвратом каретки ('\r') или возвратом каретки, за которым сразу следует перевод строки.

Но сервер не отправляет ни \n, ни \r. Пытаться

  out.write("Got your message " + message.toString() + "\n");
person Grim    schedule 25.03.2017
comment
Спасибо @Peter Rader, я попробую то, что вы предложили. - person maddie; 25.03.2017
comment
Добавление новой строки и флеш помогло. Я создаю новый поток для каждого нового сообщения с сервера. Есть ли способ уменьшить это количество потоков? Кроме того, в какой момент я должен уничтожить эти потоки? - person maddie; 25.03.2017
comment
@maddie Поток может представлять собой объект особого типа, имеющий особое состояние помимо создания экземпляра. Поток может быть запущен, так что вы имеете в виду. Количество экземпляров потока или количество запущенных потоков? - person Grim; 25.03.2017
comment
Я думаю, я был не ясен. В методе send(msg,i) я создаю новый поток new Thread() { public void run() { try { while (true) { String message = br.readLine(); System.out.println("Message received from the server : " +message); } } catch(IOException e) { e.printStackTrace(); } } }.start(); Это создает один поток для каждого сообщения, которое я получаю от сервера. Есть ли лучший способ справиться с этим? Как я могу вместо этого создать только один поток на сервер? - person maddie; 25.03.2017
comment
@maddie Это хороший вопрос, но у меня недостаточно опыта, чтобы ответить на него. Разместите свой вопрос на codereview, это может помочь. - person Grim; 25.03.2017
comment
Конечно. Спасибо. - person maddie; 25.03.2017