2014-09-28 3 views
0

Итак, я немного экспериментирую с библиотекой Kryonet, и для начала я решил разработать простую программу чата, которая позволит общаться с клиентом (удаленным компьютером) до сервер (локальная машина).Kryonet chat POC timeout issue

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

Но есть большая неприятная проблема: если клиент не отправляет какой-либо пакет (здесь пакеты являются текстовыми сообщениями) в течение определенного времени, он отключается сервером, говоря, что он был отключен.

я борюсь с этим, и я не знаю, как это исправить ...

Вот источники моих программ (за исключением закомментирована //all my imports таким образом, чтобы избежать тонн линий импорта. ..):

ChattyServer.java

package com.azsde.Chatty; 

//all my imports 

public class ChattyServer { 

    //Mes objets 
    private Server server; 
    private ArrayList <Clients> clientsList; 

    //Mes méthodes 

    //Constructeur 
    public ChattyServer() throws IOException 
    { 
     clientsList = new ArrayList <Clients>(); 
     server = new Server(); 
     registerPackets(); 
     server.addListener(new NetworkListener(clientsList)); 
     server.bind(101); 
     server.start(); 

     // Open a window to provide an easy way to stop the server. 
     JFrame frame = new JFrame("Chatty Server"); 
     frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); 
     frame.addWindowListener(new WindowAdapter() 
     { 
      public void windowClosed (WindowEvent evt) 
      { 
       server.stop(); 
      } 
     }); 

     frame.getContentPane().add(new JLabel("Close to stop the server.")); 

     JPanel panel = new JPanel(); 
     frame.getContentPane().add(panel, BorderLayout.SOUTH); 

     JButton btnNewButton = new JButton("New button"); 
     btnNewButton.addActionListener(new ActionListener() { 
      public void actionPerformed(ActionEvent arg0) { 
       //Packet3Order order = new Packet3Order(); 
       //order.start = true; 
       //server.getConnections()[0].sendTCP(order);     
       listClients();    
      } 
     }); 
     panel.add(btnNewButton); 
     frame.setSize(320, 200); 
     frame.setLocationRelativeTo(null); 
     frame.setVisible(true); 

    } 

    private void registerPackets() 
    { 
     Kryo kryo = server.getKryo(); 
     kryo.register(Packet0ConnectionRequest.class); 
     kryo.register(Packet1RequestResponse.class); 
     kryo.register(Packet2Message.class); 
     kryo.register(Packet3Order.class); 
    } 

    private void listClients() 
    { 
     for (int i = 0 ; i < clientsList.size() ; i ++) 
     { 
      if (!clientsList.isEmpty()) 
      {    
       System.out.println(clientsList.get(i).getUsername()); 
       System.out.println(clientsList.get(i).getIpAdress());    
      } 
     } 
    } 

    public static void main (String[] args) { 
     try { 
      new ChattyServer(); 
     } catch (IOException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
     Log.set(Log.LEVEL_DEBUG); 
} 
} 

NetworkListener.java (на стороне сервера)

package com.azsde.Chatty; 

//All my imports 

public class ChattyServer { 

//Mes objets 
private Server server; 
private ArrayList <Clients> clientsList; 

//Mes méthodes 

//Constructeur 
public ChattyServer() throws IOException 
{ 
    clientsList = new ArrayList <Clients>(); 
    server = new Server(); 
    registerPackets(); 
    server.addListener(new NetworkListener(clientsList)); 
    server.bind(101); 
    server.start(); 

    // Open a window to provide an easy way to stop the server. 
    JFrame frame = new JFrame("Chatty Server"); 
    frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); 
    frame.addWindowListener(new WindowAdapter() 
    { 
     public void windowClosed (WindowEvent evt) 
     { 
      server.stop(); 
     } 
    }); 

    frame.getContentPane().add(new JLabel("Close to stop the server.")); 

    JPanel panel = new JPanel(); 
    frame.getContentPane().add(panel, BorderLayout.SOUTH); 

    JButton btnNewButton = new JButton("New button"); 
    btnNewButton.addActionListener(new ActionListener() 
    { 
     public void actionPerformed(ActionEvent arg0) 
     {    
      listClients();    
     } 
    }); 
    panel.add(btnNewButton); 
    frame.setSize(320, 200); 
    frame.setLocationRelativeTo(null); 
    frame.setVisible(true); 

} 

private void registerPackets() 
{ 
    Kryo kryo = server.getKryo(); 
    kryo.register(Packet0ConnectionRequest.class); 
    kryo.register(Packet1RequestResponse.class); 
    kryo.register(Packet2Message.class); 
    kryo.register(Packet3Order.class); 
} 

private void listClients() 
{ 
    for (int i = 0 ; i < clientsList.size() ; i ++) 
    { 
     if (!clientsList.isEmpty()) 
     {    
      System.out.println(clientsList.get(i).getUsername()); 
      System.out.println(clientsList.get(i).getIpAdress());    
     } 
    } 
} 

public static void main (String[] args) 
{ 
    try { 
     new ChattyServer(); 
    } catch (IOException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 
    Log.set(Log.LEVEL_DEBUG); 
} 
} 

Packet.java (общий для сервера и клиента)

package com.azsde.Chatty; 

public class Packet { 

     public static class Packet0ConnectionRequest {String username;} 
     public static class Packet1RequestResponse {Boolean accepted = false;} 
     public static class Packet2Message {String message;} 
     public static class Packet3Order {Boolean start = false;} 

} 

ChattyClient.java

package com.azsde.Chatty; 

//My imports 

public class ChattyClient { 


    public Client client; 
    public static Scanner scanner; 

    public ChattyClient() 
    { 
      scanner = new Scanner(System.in); 
      client = new Client(); 
      register(); 
      NetworkListener nl = new NetworkListener(); 
      nl.init(client); 
      client.addListener(nl); 
      client.start(); 
      client.setKeepAliveTCP(50); 
      try 
      { 
       client.connect(50000, "127.0.0.1", 101); 
      } 
      catch (IOException e) 
      {  
       e.printStackTrace(); 
       client.close(); 
      } 
    } 

    private void register() 
    { 
     Kryo kryo = client.getKryo(); 
     kryo.register(Packet0ConnectionRequest.class); 
     kryo.register(Packet1RequestResponse.class); 
     kryo.register(Packet2Message.class); 
     kryo.register(Packet3Order.class); 
    } 

    public static void main (String[] args) 
    { 
      new ChattyClient(); 
      Log.set(Log.LEVEL_DEBUG); 
    } 
} 

NetworkListener.java (на стороне клиента)

package com.azsde.Chatty; 

//My imports 

public class NetworkListener extends Listener 

{ 
private Client client; 

public void init(Client client) 
{ 
    this.client = client; 
} 

public void connected(Connection arg0) 
{ 
    Packet0ConnectionRequest conRequest = new Packet0ConnectionRequest(); 
    conRequest.username = System.getProperty("user.name"); 
    Log.info("[CLIENT] You have connected"); 
    client.sendTCP(conRequest); 
} 

public void disconnected(Connection arg0) 
{ 
    Log.info("[CLIENT] You have disconnected."); 
} 

public void received(Connection c, Object o) 
{ 
    if (o instanceof Packet1RequestResponse) 
    { 
     Log.info("I got a response"); 
     if (((Packet1RequestResponse) o).accepted) 
     { 
      Log.info("[CLIENT] You have connected."); 
      while(true) 
      { 
       if (ChattyClient.scanner.hasNext()) 
       { 
        Log.info("Enter your message : "); 
        Packet2Message mpacket = new Packet2Message(); 
        mpacket.message = ChattyClient.scanner.nextLine(); 
        client.sendTCP(mpacket); 

       } 
      } 
     } 

     else 
     { 
      Log.info("[CLIENT] Connection failed."); 
      c.close(); 
     } 

    } 

    if (o instanceof Packet3Order) 
    { 
     Log.info("I got an order"); 
     if (((Packet3Order) o).start) Log.info("Start"); 
     else Log.info("Stop"); 
    } 
} 
} 

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

Заранее благодарю вас!

+0

Возможно, вам захочется узнать, что Stackoverflow Netiquette не рекомендуется использовать записи с надписями URL-link. Скорее, включите ее в свой пост, как только упомянутая страница (ы) не должна оставаться постоянной навсегда, чтобы по-прежнему предоставлять ваш предполагаемый контент. Возможно, вам захочется перечитать StackOverflow Do-s и Don't-s и повторно отредактировать сообщение, чтобы продемонстрировать вашу волю, чтобы соответствовать сетевому общему типу сообщества, а также избегать любого неблагоприятного шага от любого Модератора, который может чувствовать обеспечить соблюдение указанных правил. Наслаждайтесь великим Сообществом участников, в которых вы только что вошли. – user3666197

+0

Спасибо за ваш совет, я отредактировал мое сообщение и добавил свой код. – Azsde

ответ

0

Я сделал что-то очень глупое.

Имея это: mpacket.message = ChattyClient.scanner.nextLine();, моя программа ждет ввода, поэтому в течение этого периода на сервер не был отправлен пакет keepAlive.

0

Системы обмена сообщениями либо устанавливают/удаляют соединения один раз при возникновении необходимости, либо настраивают/поддерживают связь, а каналы передают с объектами контроля потока, также известными как сообщения KeepAlive (которые могут также содержать данные о телеметрии о соединении или стороне клиента/сервера состояние и т. д.).

Таким образом, на основе вашего определения задачи (держать соединения) и (во избежание T/O на неактивном состоянии (ов)) самое простое решение:

  1. оснащать ваша стратегия обмена сообщениями с aKeepAliveMsgINJECTOR на каждая сторона отправителя асинхронно огня «все еще здесь» сообщения через соединение (да, на вас уровень приложения, таким образом, не зависят от основного транспорта поддержания активности (s))
  2. реализацииanIncomingMessageFILTER на каждой стороне приемника, чтобы разделить полезный чат-контент из [[[aKeepAliveMSG]]] Signaling/полезная нагрузка управления (ов)

Сделав это, вы можете добавить больше логики в такой тривиальной сигнализации/уровня управления в ваше желание или по мере роста вашей архитектуры обмена сообщениями.

+0

Разве это не то, что client.setKeepAliveTCP (50); должен делать? – Azsde

+0

Согласно вашим собственным наблюдениям, этой установке не удалось избежать тайм-аутов и не удалось работать, не так ли? Скорее приложите свой собственный поток сообщений под вашим явным контролем, чтобы двигаться вперед от квадрата 1. Вы можете добавить UUID (ы), данные телеметрии, журнал задержек в оба конца и многое другое, чтобы диагностировать операционную среду, которая также поможет вам изолировать основную причину проблем. – user3666197