2017-08-21 12 views
0

TCP上で実行されているカスタム・プロトコル検索サービスを作成しています。 EmbeddedChannelを使用してテストする場合、すべてが完璧に機能します。さらにテストするために、私はServerを書いてハンドラを追加しました。プレーンなJavaソケットクライアントからの要求で、サーバーはデータを受信し、処理して応答を返します。ただし、応答はクライアントソケットに到達しません。私は大規模なchannelPipelineを使いこなしたかもしれないと思った。ですから、インバウンド・ハンドラにのみ実装を減らします。まだ動作しません。誰かがここで助けることができますか?シンプル・ネット・サーバーがレスポンスを送信しない

サーバー:

public void start() throws Exception{ 
    EventLoopGroup bossGroup = new NioEventLoopGroup(); 
    EventLoopGroup workerGroup = new NioEventLoopGroup(); 

    try { 
     final KaiExceptionHandler kaiExceptionHandler = new KaiExceptionHandler(); 
     ServerBootstrap b = new ServerBootstrap(); 
     b.group(bossGroup, workerGroup) 
       .channel(NioServerSocketChannel.class) 
       .childHandler(new ChannelInitializer<SocketChannel>() { 
        @Override 
        protected void initChannel(SocketChannel socketChannel) throws Exception { 
         ChannelPipeline pipeline = socketChannel.pipeline(); 
         pipeline.addLast(new SimpleHandler()); 
        } 
       }); 
     ChannelFuture future = b.bind(new InetSocketAddress("localhost", 9400)).sync(); 
     future.addListener(new ChannelFutureListener() { 
      @Override 
      public void operationComplete(ChannelFuture channelFuture) throws Exception { 
       if(channelFuture.isSuccess()) { 
        LOGGER.info("Kai Server is bounded to '{}'", "localhost:9400"); 
       }else { 
        LOGGER.error("Failed to bound Kai to 'localhost:9400'", channelFuture.cause()); 
       } 
      } 
     }); 
     future.channel().closeFuture().sync(); 
    }finally { 
     workerGroup.shutdownGracefully(); 
     bossGroup.shutdownGracefully(); 
    } 

シンプルハンドラ:

public class SimpleHandler extends ChannelInboundHandlerAdapter { 

@Override 
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { 
    Charset charset = Charset.defaultCharset(); 
    ctx.write(Unpooled.copiedBuffer("Client is not seeing this", charset)); 
    ctx.flush(); 
} 

@Override 
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { 
    ctx.flush(); 
} } 

テストクライアント。きちんとした実装ではありません。しかし、テストのためだけです。

public class TestClient { 


public static void main(String[] args) throws Exception { 

    Socket socket = new Socket("localhost", 9400); 
    InputStream is = socket.getInputStream(); 
    StringBuilder sb = new StringBuilder(); 
    byte[] buffer = new byte[64]; 
    int r = 0; 
    socket.setSoTimeout(10000); 
    System.out.println("Reading..."); 
    while ((r = is.read(buffer)) != -1) { 
     sb.append(new String(buffer).trim()); 
    } 
    System.out.println("String: " + sb.toString()); 
} 

}

答えて

1

あなたのテストプログラムは、接続がデータを書き込んだ後にクローズされることを想定しており、その仮定文字列はマルチバイト文字を送信する場合には断片化されていません。

ソケットの閉鎖までの待ち時間が意図的である場合は、次のようにあなたのwrite文を変更する必要があります。

ctx.write(Unpooled.copiedBuffer("Client is not seeing this", charset)) 
    .addListener(ChannelFutureListener.CLOSE); 

あなたが再オープンし、別のソケット接続のたびに必要があるため、通信のこの方法は、しかし、非効率的ですサーバーに何か言いたいことがあります。最善の方法は、プロトコルをラインベースにするか、長さフィールドで区切ってから、クライアントでBufferedReaderを使用して1行ずつ応答を読み込み、サーバー側ですべてのメッセージの最後に改行を追加することです。

包みなさい、サーバーがメッセージを受信する必要がある、あなたはネッティーが自動的に文字列にByteBuf Sをオンさせるために、オプションのnew StringDecoder()続く、あなたのパイプラインの開始時にnew LineBasedFrameDecoder()を追加する必要があり、あなたはもうこれを行う必要はありません。 NettyはStringEncoderを使用してこれを逆に行うこともできるので、毎回ByteBufにラップするのではなく、文字列オブジェクトを書くことができます。

+0

。 'read(buffer)!= -1'は、サーバがソケットを閉じる場合にtrueを保持します。しかし、私はそれを望んでいません。プロトコルはバイナリベースです。要求と応答は17バイトの固定ヘッダーサイズとバイナリ形式の任意の本文でバイナリ形式で送信されます。ヘッダーから読み取る正確な応答の本文サイズを知っているときに区切り記号が必要ですか?はいの場合、どうですか? –

0

最後の問題が見えます。全体の問題は、テストクライアントにありました。

最初の問題:read(buffer) != -1は、ソケットが閉じられることを期待しているFerrybigによって最初のものが指し示されました(その人に感謝します)。

第2の問題:
第2の理由は、ChannelInboundHandlerAdapter#channelRead(ChannelHandlerContext ctx, Object msg)は、ソケットが何も送信しないため、何も読み取られなかったので、決して呼ばれませんでした。何かを送るために私のクライアントを編集することはそれを働かせる。

新しいクライアント:私は見

public class TestClient { 


public static void main(String[] args) throws Exception { 

    Socket socket = new Socket("localhost", 9400); 
    socket.setSoTimeout(10000); 
    OutputStream raw = socket.getOutputStream(); 
    // Will be the request bytes 
    raw.write(1); 
    raw.flush(); 

    InputStream is = socket.getInputStream(); 
    StringBuilder response = new StringBuilder(); 
    // actual expected size will be here 
    final int expectedResponse = 128; 
    byte[] buffer = new byte[expectedResponse]; 
    int bytesRead = is.read(buffer); 
    if (bytesRead != -1) { 
     response.append(new String(buffer).trim()).append("\n"); 
    } 
    System.out.println("String: " + response.toString()); 
} 

}

関連する問題