1

私のプロトコルの一部として、新しい接続が確立されたときにクライアントにバージョン番号を送信してもらいたいです。これはパイプラインの別のハンドラーで実行したいので、これはかなり基本的な質問かもしれませんが、どうすればよいかわかりませんので、ご容赦ください。もう 1 つは、接続 (パイプライン) を介して POJO を前後に送信できるようにしたいということです。また、認証ハンドラーを追加したいと思います。とにかく、現在、何らかのエラーが発生しています。これは、バージョン チェックがパイプラインから適切に消化されていないためだと確信しています。

基本的に、以下のコードは、接続が確立されたときにバージョンがチェックされた後にサーバーが出力する「Hello World」を送信するように設定されています。少なくとも理論的には、実際にはこれはうまくいきません ;)

現在私は持っています:

クライアント.java

public static void main(String[] args)
{
    ...

    // Set up the pipeline factory.
    bootstrap.setPipelineFactory(new ChannelPipelineFactory() 
    {
        @Override
        public ChannelPipeline getPipeline() throws Exception 
        {
            return Channels.pipeline(
                    new ObjectEncoder(),
                    new ObjectDecoder(),
                    new VersionClientHandler(),
                    new BusinessLogicClientHandler());
        }
    });     

    ...

    // The idea is that it will all be request and response. Much like http but with pojo's. 
    ChannelFuture lastWriteFuture = channel.write("Hello world".getBytes());

    if (lastWriteFuture != null) 
    {
        System.out.println("waiting for message to be sent");
           lastWriteFuture.awaitUninterruptibly();
    }

    ...
}

VersionClientHandler.java

public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e)
{
    ChannelBuffer versionBuffer = ChannelBuffers.buffer(VERSION_STRING_LENGTH);
    versionBuffer.writeBytes("v123.45a".getBytes());
    // If I understand correctly, the next line says use the rest of the stream to do what you need to the next Handler in the pipeline?
    Channels.write(ctx, e.getFuture(), versionBuffer);  
}

BusinessLogicClientHandler.java

Not really doing anything at this point. Should it?

サーバー.java

public static void main(String[] args)
{
    ...

    public ChannelPipeline getPipeline() throws Exception 
    {
        return Channels.pipeline(
                new ObjectEncoder(),
                new ObjectDecoder(),
                new VersionServerHandler(),
                new BusinessLogicServerHandler());
    }

    ...
}

VersionServerHandler.java

public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) 
{
    ChannelBuffer versionBuffer = ChannelBuffers.buffer(VERSION_NUMBER_MAX_SIZE);
    System.out.println("isReadable - messageReceived: " + versionBuffer.readable()); // returns false???
    // Basically I want to read it and confirm the client and server versions match.
    // And if the match fails either send a message or throw an exception
    // How do I also pass on the stream to the next Handler? 
}

BusinessLogicServerHandler.java

public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) 
{
    e.getMessage();
    byte[] message = (byte[])e.getMessage(); // "Hello World" in byte[] from Client.java
}

基本的に私が望むのは、通信プロトコルの一部としてチャネルが接続されたときにバージョン番号が渡され、検証されることです。すべてが舞台裏で自動的に行われます。同様に、この方法で認証メカニズムを渡したいと思います。

セキュア チャットの例でやりたかったことと多少似ているコードを見たことがありますが、実際には理解できませんでした。このコードをセットアップする方法についてのヘルプは本当にありがたいです. 1 つの大規模なハンドラーですべてを実行できることはわかっていますが、それがパイプラインのポイントであり、論理的に意味のある単位に分割することです。

4

4 に答える 4

2

解決策を見つけました!!!

いくつかの問題がありました。

VersionClientHandler の新しいコードは次のとおりです。

public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e)
{
    String verison = "v123.45a";

    ChannelBuffer versionBuffer = ChannelBuffers.buffer(VERSION_STRING_LENGTH);
    versionBuffer.writeBytes(version.getBytes());
    e.getChannel().write(version);
}

I'm not sure for the reasone.getChannel().write(version);ではなく、最後の行に注目してください。実際、何もしないように見えるので、そこに ChannelBuffers コードがある理由を調べ始めようとしています...Channels.write(ctx, e.getFuture(), versionBuffer);

VersionServerHandler.java では、次のようになりました。

public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) 
{
    String versionCheck = (String)e.getMessage();
    System.out.println("VersionServerHandler - " + versionCheck);
    ctx.getPipeline().remove(VersionServerHandler.class);
}

バッファーを読み取らずe.getMessage()、正しい型のオブジェクトにキャストするだけであることに注意してください。ctx.getPipeline().remove(VersionServerHandler.class);この上に、それ以降の処理からそのハンドラーを削除するためにそこにあるものを追加しました。最初の接続後は必要ありません。そのヒントをくれたデニスに感謝します。

結論

残りは私が期待した通りです。重要なのは、バッファを読み取って情報を渡す方法を正しく理解していなかったことです。また、エラー メッセージと例はあまり明確ではありませんでした。Netty から POJO チャネルをパイプラインに追加したらすぐに、すべてのハンドラーに対してオブジェクトのみの処理を開始する必要があります。私はそれを逃した。コンセプトは正しかったのですが、チャネルからデータを読み取ろうとした方法が間違っていました。

もう 1 つの大きなヒントは、最初の接続後にハンドラーが必要ない場合は、パイプラインからハンドラーを削除することです。認証ハンドラーについても同じことが当てはまると思います。ここで確認できれば素晴らしいのですが、それは後で調べなければなりません。

于 2012-01-21T18:32:06.827 に答える
0

カスタムハンドラーを追加することで、やりたいことを簡単にアーカイブできると思います。したがって、バージョンチェックでは、channelConnected(....)をオーバーライドするハンドラーを追加し、そこでrheチェックを実行できます。authの場合、バージョンチェックの後にmessageRecieved(....)メソッドをオーバーライドする別のハンドラーを追加するだけです。認証が完了したら、パイプラインからハンドラーを削除し、必要に応じて再度追加できます。

BusinessLogicハンドラーは、最後のハンドラーとしてパイプラインに配置する必要があります。ハンドラーのいずれかがブロック操作を実行することに注意してください。その前にExecutionHandlerを追加して、ioworkerスレッドがブロックされないようにし、nettyサーバーを無責任にすることを検討する必要があります。

于 2012-01-21T16:44:45.717 に答える
0

表示されているエラーの内容については言及していません。

いずれにせよ、バージョン チェックを行うために別のチャネル ハンドラを使用することはお勧めしません。主な理由は、バージョン チェックは、接続が最初に確立されたときに 1 回だけ行う必要があるためです。また、チャネル ハンドラーは、バイトを pojo に変換するなど、トランスポート層の問題を処理するのが最善であると考えているためです。

于 2012-01-16T17:45:27.173 に答える
0

簡単な例を作成しました: https://github.com/boldt/netty-examples/

新しい接続が確立されると、バージョン番号が返されます。これは、バージョンがチャネルに書き込まれた後にパイプラインから削除される別のハンドラーで行われます。その後、netty チュートリアルの ECHO の例です。

サーバーへのAtelnet localhost 1234はすぐにバージョンを示します。

このように、バージョン ハンドラーの背後にあるパイプラインに認証ハンドラーを追加できます。

于 2012-01-21T02:48:35.780 に答える