Java 为什么客户端在使用Netty从服务器连续获取图像时会阻塞?
我想在客户端上实时显示远程桌面。即服务器不断发送屏幕截图,客户端同时在面板上绘制图像。它在开始时运行良好,但几分钟后客户端将阻塞,服务器正常运行 为屏幕截图定义的CaptureImage类。它有两个属性,长度和内容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
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