我必须将大量数据发送到以小块连接到我的服务器的客户端。
所以,我有类似的东西:
for(;;) {
messageEvent.getChannel().write("Hello World");
}
问题是,由于某种原因,客户端正在接收脏数据,比如Netty缓冲区在每次迭代时都不清楚,所以我们得到类似“Hello WorldHello”的内容。
如果我在代码中做了一点改变,让线程睡眠一切正常:
for(;;) {
messageEvent.getChannel().write("Hello World");
Thread.sleep(1000);
}
答案 0 :(得分:1)
正如MRAB所说,如果服务器在通道上发送多条消息而没有指出每条消息的结束,那么客户端就不能总是正确地读取消息。通过在写入消息后添加休眠时间,也无法解决问题的根本原因。
要解决此问题,必须以其他方可识别的方式标记每条消息的结尾,如果客户端和服务器都使用Netty,则可以在json处理程序之前添加LengthFieldPrepender和LengthFieldBasedFrameDecoder。
String encodedMsg = new Gson().toJson(
sendToClient,newTypeToken<ArrayList<CoordinateVO>>() {}.getType());
默认情况下,Gson使用html转义内容,有时会导致有线编码,如果需要使用Gson工厂,可以禁用此功能
final static GsonBuilder gsonBuilder = new GsonBuilder().disableHtmlEscaping();
....
String encodedMsg = gsonBuilder.create().toJson(object);
答案 1 :(得分:0)
在这两种情况下,您都不会发送任何内容来指示一个项目的结束位置和下一个项目的开始时间,或者每个项目的持续时间。
在第二种情况下,睡眠会使通道超时并刷新,因此客户端会看到“中断”,它会将其解释为项目的结尾。
答案 2 :(得分:0)
客户端永远不应该看到这个“脏数据”。如果确实如此,那就是一个bug。但是,我要想到任何可能导致这种情况发生的事情。因为每个Channel.write(..)事件都会被添加到一个队列中,然后在可能的情况下写入客户端。因此,write(..)方法中传递的每个数据都将被写入。没有“concat”的数据。
管道中是否有一些自定义编码器可以在将数据发送到客户端之前缓冲数据?
如果您能够显示提供此行为的完整代码,那么我们也可以看到管道中的处理程序等。