4Manuals

  • PDF Cloud HOME

基于Netty的TCP服务器,从客户端接收很长的字符串时出现问题 Download

    春季启动-Couchbase AbstractCouchbaseConfiguration-如何避免覆盖不必要的方法 我不知道(未解决的编译问题:) 加载数据并推送到未显示的RecyclerView中 调用Model类的函数时出现java.lang.NullPointerException 字符串数组在for循环中初始化时忽略索引0 Spring MVC @ModelAttribute未填充AJAX发布请求 需要建议在Java中使用哪个数据库/存储来存储RaftLogs(实现Raft Consensus Algorithm) Flutter:Java使用或覆盖已弃用的API @ EnableOAuth2Sso和@EnableResourceServer(同一应用程序中的客户端和资源行为) 中断可运行线程的问题

我需要为另一个应用程序(客户端)公开一个TCP服务器接口,这是我的大学用于处理某些研究的程序。我使用Netty来完成任务。而且在大多数情况下都可以正常工作。

但是,当客户端发送大块字符串(例如一百万个或更多字符)时,就会出现问题。

在通道处理程序(下面的代码)中,channelRead0接收数据(每块65,536个字符)。但是有时,并不是每次都在整个文本被接收之前调用channelReadComplete,这会导致整个消息被无意地拆分为2。但是服务器和客户端上似乎都没有异常。

服务器接收的字符串很重要,它不包含换行符。

我的Netty服务器,这很简单:

public class TCPServer{
    EventLoopGroup connectionGroup = new NioEventLoopGroup();
    EventLoopGroup workerGroup = new NioEventLoopGroup();
    void start(int port) throws InterruptedException {
        try {
            ServerBootstrap b = new ServerBootstrap();
            b.group(connectionGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)
                    .childHandler(new TCPChannelInitializer())
                    .option(ChannelOption.SO_BACKLOG, 128)
                    .childOption(ChannelOption.SO_KEEPALIVE, true);

            ChannelFuture f = b.bind(port).sync();
            if(f.isSuccess()){
                // ...
            }
            f.channel().closeFuture().sync();
        } finally {
            workerGroup.shutdownGracefully();
            connectionGroup.shutdownGracefully();
        }
    }

    void stop(){
        workerGroup.shutdownGracefully();
        connectionGroup.shutdownGracefully();
    }
}

我的管道很简单:

public class TCPChannelInitializer extends ChannelInitializer<SocketChannel> {
    protected void initChannel(SocketChannel socketChannel) throws Exception {
        socketChannel.pipeline().addLast(new StringEncoder());
        socketChannel.pipeline().addLast(new StringDecoder());
        socketChannel.pipeline().addLast(new SimpleHandler());
    }
}

处理程序:

public class SimpleHandler extends SimpleChannelInboundHandler {
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {
        String received = (String) msg;
        // Save chunk of string somewhere

    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
         // Whole message is supposedly here
         // Call a blocking logic function here that processes the received string

        ctx.write("{\"result\": \"some result sent back to the server\"}");
        ctx.flush();
        super.channelReadComplete(ctx);
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        ctx.close();
    }
}

客户端未使用Netty,因为它是可以正常工作的旧代码。但是,即使比更改服务器更难,我当然也可以更改客户端。

为这个服务器编写的客户端相当简单,

   try (var socket = new Socket(host, port)) {
            var in = new Scanner(socket.getInputStream());
            var out = socket.getOutputStream();

            try {
                Thread.sleep(withDelay);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            // line is just a string of an absolutely random length (without line breaks)
            System.out.println(String.format("Sending text of length: %d", line.length()));
            byte[] bArr = line.getBytes();
            try {
                out.write(bArr, 0, bArr.length);
                out.flush();
                System.out.println(in.nextLine());
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

虽然显然非常简单,但是该客户端显然可以与以前的服务器实现一起很好地工作,不幸的是,该客户端丢失了并且无法恢复。

那么问题可能出在哪里?当客户发送一个很长的字符串(一百万个或更多字符)时,为什么Netty有时会过早调用channelReadComplete? 是否存在一些大小限制,超时或其他我可能会缺少的东西?

0 个答案:

没有答案



Similar searches
    如何将ajax jquery过程的结果发送到编辑表单? 反应:添加多个动态字段 父组件未在Vue中接收子事件 检测摄像头角度是否改变 Z3的“ ctx-solver-simplify”和“ ctx-simplify”之间的可满足性不一致