Я не понимаю, почему одна из моих клиентских программ не может отправить более одного сообщения на сервер? - PullRequest
0 голосов
/ 11 апреля 2020

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

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

Здесь конструктор для моего класса сервера:

   public MyServer () {
      setUpConnection ();
   }

Вот код, который подключает клиента к порту:

   public void setUpConnection () {
     clientOutputStreams = new ArrayList ();
     try {
       serverSocket = new ServerSocket (5000);
     while (true) {
       Socket clientSocket = serverSocket.accept ();
       printWriter = new PrintWriter (clientSocket.getOutputStream ());
       clientOutputStreams.add (printWriter);

       Thread thread = new Thread (new clientHandler (clientSocket));
       thread.start();

       System.out.println ("Client is connected to server");
     }    
    } catch (Exception e) {
       e.printStackTrace ();
    }
  }

Это код, который отправляет сообщения, полученные сервером на другие клиенты:

    public void tell everyone (String message) {
     Iterator outputObject = clientOutputStreams.iterator();

     while (outputObject.hasNext()) {
        try {
            PrintWriter writer = (PrintWriter) outputObject.next();
            writer.println (message);
            writer.flush ();
        } catch (Exception e) {
            e.printStackTrace ();
        }
     }
 }

Этот код выполняется в отдельном потоке, который прослушивает сообщения, отправленные клиентами:

    public class clientHandler implements Runnable {

       Socket clientSocket;

       public clientHandler (Socket socket) {
          try {
           clientSocket = socket;
           isr = new InputStreamReader (clientSocket.getInputStream());
           reader = new BufferedReader (isr); 
          } catch (Exception e) {
          e.printStackTrace ();
       }
    }

    public void run () {
        String message;

      try {
        while ((message = reader.readLine()) != null) {
            System.out.println ("I recieved message: " + message);
            tellEveryone (message);
        }  
      } catch (Exception e) {
          e.printStackTrace();
      }
     }
    }
 }

Вот конструктор для моего класса клиента:

   public MyClient() {
      initComponents();
      setUpConnection ();
      Thread thread = new Thread (new recievingMessages ());
      thread.start ();
      jtaRec.setEditable (false);
      jtfSend.addFocusListener (this);
      jtfSend.requestFocus();
   }                

Вот код, который запускается, когда клиент нажимает кнопку отправки:

private void sendButtonActionPerformed(java.awt.event.ActionEvent evt) {                                           
    try {
        writer.println (jtfSend.getText ());
        System.out.println (jtfSend.getText ());
        writer.flush ();
        System.out.println ("message has sent");
    } catch (Exception e) {
        e.printStackTrace ();
    }//CLOSE CATCH STATEMENT
    jtfSend.setText ("");
    jtfSend.requestFocus();
}                                          

Вот код, который соединяет клиента с сервером:

public void setUpConnection () {
  try {
    socket = new Socket ("127.0.0.1", 5000);
    writer = new PrintWriter (socket.getOutputStream ());
    stream = new InputStreamReader (socket.getInputStream ());
    reader = new BufferedReader (stream);

    System.out.println ("Connection Made");
  } catch (Exception e) {
      e.printStackTrace ();
  }
}

Вот код запускается в отдельном потоке и прослушивает сообщения, отправленные сервером:

  public class recievingMessages implements Runnable {
      public void run () {
        String message;
        try {
         while ((message = reader.readLine ()) != null) {
            jtaRec.append (message + "\n");
            System.out.println ("I recieved the message" + " " + message);
         }
        } catch (Exception e) {
           e.printStackTrace();
       }
    }
  }

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

1 Ответ

0 голосов
/ 12 апреля 2020

Я немного поиграл с вашим сетевым кодом, и он, кажется, работает нормально.

Я имею в виду, что оба клиента смогли отправлять и получать несколько сообщений:

#### server logs ####           ### Jack logs ###           ### Gill logs ###
Starting server
Client is connected to server   Jack connected
SRV:1 received: Jack: Aa #1     SND:Jack - Jack: Aa #1
                                RCV:Jack - Jack: Aa #1
Client is connected to server   SND:Jack - Jack: Aa #2      Gill connected
SRV:1 received: Jack: Aa #2     RCV:Jack - Jack: Aa #2      RCV:Gill - Jack: Aa #2
SRV:2 received: Gill: Zz #1     RCV:Jack - Gill: Zz #1      RCV:Gill - Gill: Zz #1
                                                            SND:Gill - Gill: Zz #1
SRV:2 received: Gill: Zz #2     RCV:Jack - Gill: Zz #2      RCV:Gill - Gill: Zz #2
                                                            SND:Gill - Gill: Zz #2
SRV:1 received: Jack: Aa #3     RCV:Jack - Jack: Aa #3      RCV:Gill - Jack: Aa #3
                                SND:Jack - Jack: Aa #3
SRV:2 received: Gill: Zz #3     RCV:Jack - Gill: Zz #3      RCV:Gill - Gill: Zz #3
                                                            SND:Gill - Gill: Zz #3
SRV:2 received: Gill: Zz #4     RCV:Jack - Gill: Zz #4      RCV:Gill - Gill: Zz #4
                                                            SND:Gill - Gill: Zz #4
SRV:1 received: Jack: Aa #4     SND:Jack - Jack: Aa #4
                                RCV:Jack - Jack: Aa #4      RCV:Gill - Jack: Aa #4
SRV:2 received: Gill: Zz #5     RCV:Jack - Gill: Zz #       RCV:Gill - Gill: Zz #5
                                                            SND:Gill - Gill: Zz #5
SRV:1 received: Jack: Aa #5     SND:Jack - Jack: Aa #5
                                RCV:Jack - Jack: Aa #5

Большинство скорее всего, в вашем случае один из клиентов подключился слишком поздно и не смог получить всю историю, так как эта функция не реализована на стороне сервера.

Кроме того, один из ваших клиентов мог отключиться слишком рано и потерять часть истории.

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

Возможно, компоненты пользовательского интерфейса не смогут обновиться, если вы изменили их вне потока GUI, поэтому может помочь вызов jtaRec.revalidate().

...