Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/361.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/opencv/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 为什么客户端在使用Netty从服务器连续获取图像时会阻塞?_Java_Networking_Netty - Fatal编程技术网

Java 为什么客户端在使用Netty从服务器连续获取图像时会阻塞?

Java 为什么客户端在使用Netty从服务器连续获取图像时会阻塞?,java,networking,netty,Java,Networking,Netty,我想在客户端上实时显示远程桌面。即服务器不断发送屏幕截图,客户端同时在面板上绘制图像。它在开始时运行良好,但几分钟后客户端将阻塞,服务器正常运行 为屏幕截图定义的CaptureImage类。它有两个属性,长度和内容 private int length;// The length of attribute content private byte[] content;// The BufferedImage convert to bytearray 服务器的主要代码: public class

我想在客户端上实时显示远程桌面。即服务器不断发送屏幕截图,客户端同时在面板上绘制图像。它在开始时运行良好,但几分钟后客户端将阻塞,服务器正常运行

为屏幕截图定义的CaptureImage类。它有两个属性,长度和内容

private int length;// The length of attribute content
private byte[] content;// The BufferedImage convert to bytearray
服务器的主要代码:

public class ServerHandler extends ChannelInboundHandlerAdapter {
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        BufferedImage image;
        Robot robot = new Robot();
        Toolkit toolkit = Toolkit.getDefaultToolkit();
        Rectangle rect = new Rectangle(0, 0, toolkit.getScreenSize().width, toolkit.getScreenSize().height);
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        CaptureImage captureImage = new CaptureImage();
        while (true) {
            image = robot.createScreenCapture(rect);
            ImageIO.write(image, "jpg", baos);
            captureImage.setLength(baos.toByteArray().length);
            captureImage.setContent(baos.toByteArray());
            ctx.writeAndFlush(captureImage);// Deliver to ImageEncoder before writing
            Thread.sleep(100);
            baos.reset();
            // Always print if add System.out.println() here...
        }
    }
}

public class ImageEncoder extends MessageToByteEncoder<CaptureImage> {
    @Override
    protected void encode(ChannelHandlerContext ctx, CaptureImage msg, ByteBuf out) throws Exception {
        out.writeInt(msg.getLength());
        out.writeBytes(msg.getContent());
    }
}
公共类ServerHandler扩展ChannelInboundHandlerAdapter{
@凌驾
public void channelRead(ChannelHandlerContext ctx,Object msg)引发异常{
缓冲图像;
机器人=新机器人();
Toolkit=Toolkit.getDefaultToolkit();
矩形rect=新矩形(0,0,toolkit.getScreenSize().width,toolkit.getScreenSize().height);
ByteArrayOutputStream bas=新的ByteArrayOutputStream();
CaptureImage CaptureImage=新CaptureImage();
while(true){
image=robot.createScreenscapture(rect);
ImageIO.write(图像,“jpg”,baos);
setLength(baos.toByteArray().length);
setContent(baos.toByteArray());
ctx.writeAndFlush(captureImage);//在写入之前提交给ImageEncoder
睡眠(100);
重置();
//如果在此处添加System.out.println(),则始终打印。。。
}
}
}
公共类ImageEncoder扩展MessageToByteEncoder{
@凌驾
受保护的无效编码(ChannelHandlerContext ctx、CaptureImage msg、ByteBuf out)引发异常{
out.writeInt(msg.getLength());
out.writeBytes(msg.getContent());
}
}
客户端的主要代码:

public class ClientHandler extends ChannelInboundHandlerAdapter {
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        // Accept msg from ImageDecoder
        CaptureImage captureImage = (CaptureImage) msg;
        RemoteDesktop.panel.display(captureImage.getContent());// Paint the image on the panel
    }
}

public class ImageDecoder extends ReplayingDecoder<Void> {
    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
        int length = in.readInt();

        byte[] content = new byte[length];
        in.readBytes(content);

        CaptureImage captureImage = new CaptureImage();
        captureImage.setLength(length);
        captureImage.setContent(content);

        out.add(captureImage);
        // The print will stop after a few minutes if add System.out.println() here...
    }
}
公共类ClientHandler扩展了ChannelInboundHandlerAdapter{
@凌驾
public void channelRead(ChannelHandlerContext ctx,Object msg)引发异常{
//接受来自ImageDecoder的消息
CaptureImage CaptureImage=(CaptureImage)消息;
RemoteDesktop.panel.display(captureImage.getContent());//在面板上绘制图像
}
}
公共类ImageDecoder扩展了ReplayDecoder{
@凌驾
受保护的无效解码(ChannelHandlerContext ctx、ByteBuf输入、列表输出)引发异常{
int length=in.readInt();
字节[]内容=新字节[长度];
in.readBytes(内容);
CaptureImage CaptureImage=新CaptureImage();
captureImage.setLength(长度);
captureImage.setContent(content);
out.add(captureImage);
//如果在此处添加System.out.println(),几分钟后打印将停止。。。
}
}
ServerHandler中的打印一直在进行,但ImageDecoder中的打印可能会在几分钟后停止

我遇到的问题看起来像OutOfMemoryError。但即使我在每个ChannelHandler中重写exceptionCaught方法,也不会出现任何错误消息。我也试过内存分析器,但似乎没有帮助

请帮我找出关键原因


此处是可运行项目

这是因为服务器发送图像太快,而客户端速度太慢。在这种情况下,由于客户端的入站netty缓冲区被填满,客户端将耗尽内存

服务器代码的更好设计是在发送下一条消息之前等待客户机的确认(在给定的时间段内)。客户端在处理完当前消息后可以发送ack