Java 内蒂写了几封信

Java 内蒂写了几封信,java,netty,channel,Java,Netty,Channel,我和这里有同样的问题,我解决不了。以下是一些案例: 我可以从客户端发送多条消息,服务器只有在没有响应时才会接收。 如果我向服务器发送一条消息,并且它使用handler处理、生成并写入刷新响应,那么通道将切换到closed,并且我无法从客户端发送更多消息。 如果我使用write方法从客户机发送消息,消息不会到达服务器,因为需要刷新。它不会关闭频道。 当生成响应并writeAndFlush时,问题似乎出现在服务器端 我正在开发一个RTSP客户机/服务器,该协议基于HTTP/1.1,遵循Snoop H

我和这里有同样的问题,我解决不了。以下是一些案例:

我可以从客户端发送多条消息,服务器只有在没有响应时才会接收。 如果我向服务器发送一条消息,并且它使用handler处理、生成并写入刷新响应,那么通道将切换到closed,并且我无法从客户端发送更多消息。 如果我使用write方法从客户机发送消息,消息不会到达服务器,因为需要刷新。它不会关闭频道。 当生成响应并writeAndFlush时,问题似乎出现在服务器端

我正在开发一个RTSP客户机/服务器,该协议基于HTTP/1.1,遵循Snoop HTTP Server的Netty文档,如果使用keep alive选项,则消息只会写入,不会刷新。在我的用例中,我重复一遍,消息不会到达服务器

以下是一些代码:

客户端

第二个选项不起任何作用


对于Netty 3.2,我没有这个问题,它可以与send方法一起正常工作。

Netty 4的HTTP解码器总是生成HttpMessage+1或更多HttpContent。如果您希望Netty将它们合并到单个FullHttpMessage中,请将HttpObjectAggregator插入管道中。谢谢您信任,我的问题是客户端处理程序中的方法exceptionCaught在发生异常时默认关闭通道。现在问题解决了。您可能会更新您的问题并发布一个自我回答,以备将来使用:-
    // Bootstrap
    public RtspClient(String host, String port) throws NumberFormatException, InterruptedException{
                  // Configure the client.
                  EventLoopGroup group = new NioEventLoopGroup();
                  try {
                      b = new Bootstrap();
                      b.group(group)
                       .channel(NioSocketChannel.class)
                       .handler(new RtspClientInitializer());

                      ch = b.connect(host, Integer.parseInt(port)).sync().channel();

                 } finally {
                     // Shut down executor threads to exit.
                     // group.shutdownGracefully();
                 }
    }

     // Channel Pipeline definition
     class RtspClientInitializer extends ChannelInitializer<SocketChannel> {
        @Override
          public void initChannel(SocketChannel ch) {
              ChannelPipeline p = ch.pipeline();
              p.addLast("encoder", new RtspRequestEncoder());
              p.addLast("decoder", new RtspResponseDecoder());
              p.addLast("handler", new RtspClientHandler());
          }
      }

      // The method which sends RTSP OPTIONS protocol method
      public void sendOptions() throws InterruptedException{

        // HTTP/RTSP request.
        DefaultFullHttpRequest request = new DefaultFullHttpRequest(
        RtspVersions.RTSP_1_0, RtspMethods.OPTIONS, "*");
        request.headers().set(RtspHeaders.Names.CONNECTION, RtspHeaders.Values.KEEP_ALIVE);
        request.headers().set(RtspHeaders.Names.CONTENT_LENGTH, request.content().readableBytes());
        request.headers().set(RtspHeaders.Names.CSEQ, this.CSeq);
        this.CSeq++;

        // Write to channel

        System.out.println("Request: ------------------------------------------------------");
        System.out.println(request.toString());
        System.out.println("---------------------------------------------------------------");

        ch.writeAndFlush(request);

      }
    // Bootstrap
    public void initRtspServer() throws InterruptedException{
        EventLoopGroup bossGroup = new NioEventLoopGroup(1);
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        try {
            ServerBootstrap b = new ServerBootstrap();
            b.group(bossGroup, workerGroup)
             .channel(NioServerSocketChannel.class)
             .handler(new LoggingHandler(LogLevel.INFO)).childHandler(new RtspServerInitializer());

            ChannelFuture cf = b.bind(this.port);

            System.err.println("RTSP Server run at this URL: " +
                    "rtsp" + "://127.0.0.1:" + this.port + '/');

            cf.channel().closeFuture().sync();

    } finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
    }


    // Channel Pipeline definition
    class RtspServerInitializer extends ChannelInitializer<SocketChannel>{

        @Override
        public void initChannel(SocketChannel ch) {
            ChannelPipeline p = ch.pipeline();
            p.addLast("decoder",new RtspRequestDecoder());
            p.addLast("encoder",new RtspResponseEncoder());
            p.addLast("handler",new RtspServerHandler());
        }
     }

     // In this case I only handle the OPTIONS method on server-side
     class RtspServerHandler extends SimpleChannelInboundHandler<HttpRequest> {

        private HttpRequest request;
        private FullHttpResponse response;

        @Override
        protected void channelRead0(ChannelHandlerContext ctx, HttpRequest request)
                throws Exception {

        this.response = new DefaultFullHttpResponse(RTSP_1_0,OK);
            String sequence = request.headers().get(RtspHeaders.Names.CSEQ);
            this.response.headers().set(RtspHeaders.Names.CSEQ, sequence);
            this.response.headers().set(RtspHeaders.Names.PUBLIC, "OPTIONS,SETUP,TEARDOWN,PLAY");
            ctx.writeAndFlush(response).isSuccess(); // I think server closes the channel here

        }
    }
        RtspClient client = new RtspClient("127.0.0.1","554");
        client.sendOptions();
        Thread.sleep(1000);
        client.sendOptions();