0

そこで、私は Kryonet ライブラリを少し試しており、まずクライアント (リモート コンピューター) からサーバー (ローカル マシン) への通信を可能にする単純なチャット プログラムを開発することにしました。

クライアントからサーバーへのメッセージを受信できます。

しかし、厄介な問題があります。クライアントがパケット (ここではパケットはテキスト メッセージです) を一定時間送信しないと、サーバーからタイムアウトとして切断されます。

私はこれに苦労していて、これを修正する方法がわかりません...

//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");
    }
}
}

誰かが私が間違っていることを教えてもらえますか? クライアントが長時間アイドル状態になっても、クライアントとサーバー間の接続を維持したいと考えています。

前もって感謝します !

4

2 に答える 2

0

メッセージング システムは、必要に応じて接続をセットアップ/破棄するか、接続をセットアップ/維持し、KeepAlive メッセージとも呼ばれるフロー制御オブジェクトをチャネルに供給します (これには、接続またはクライアント/サーバー側の状態などに関するテレメトリの詳細も含まれる場合があります)。

したがって、タスク定義(接続を維持する)および(アイドル状態での T/O を回避する)に基づく最も簡単な解決策は次のとおりです。

  1. メッセージング戦略を各送信者側に装備aKeepAliveMsgINJECTORして、接続を介して「まだここにある」メッセージを非同期に起動します(はい、アプリケーションレベルで、基礎となるトランスポートキープアライブとは無関係です)
  2. anIncomingMessageFILTER[[[aKeepAliveMSG]]] シグナリング/コントロール ペイロードから有用なチャット コンテンツを分割するために、各受信側に実装する

そうすることで、必要に応じて、またはメッセージングアーキテクチャのニーズが大きくなるにつれて、そのような簡単なシグナリング/制御レイヤーにロジックを追加できます。

于 2014-09-29T12:06:16.107 に答える
0

私はとてもばかげたことをしました。

これmpacket.message = ChattyClient.scanner.nextLine();があると、プログラムが入力を待機するようになるため、この期間中、keepAlive パケットはサーバーに送信されませんでした。

于 2014-10-05T20:42:23.903 に答える