netty怎么实现客户端和服务端传输文件和json串

江火似流萤 发布于 03/25 00:40
阅读 249
收藏 0

思路:定义文件传输的指令,将文件转化为bete数组流,将byte数组流流加密成base64,放到我们定义好的对象里面

转成json串,发送给服务端,服务端通过解码器拿到对象,获取文件执行 对base 解码写入到服务器上面

整体思路是这样,目前遇到的问题就是 base64太长无法放到字符串中,

把编码器和解码器相关代码贴上 目前可以实现json的传输,对于文件流还是不行,大家socket这块比较熟悉的可以指导一下,万分感谢,有好的解决方案也可以提一下。

@Slf4j
public class DeviceCommandDecoder extends MessageToMessageDecoder<ByteBuf> {
    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf msg, List<Object> out) throws Exception {
        String jsonString = msg.toString(StandardCharsets.UTF_8).trim();
        String removeSpaceJsonString = jsonString.replace("\\r\\n","");
        log.info("removeSpaceJsonString:{}",removeSpaceJsonString);
        ToServerCommand toServerCommand = JSON.parseObject(removeSpaceJsonString, ToServerCommand.class);
        out.add(toServerCommand);
    }

  
}
public class DeviceCommandEncoder extends MessageToByteEncoder<Object> {
    @Override
    protected void encode(ChannelHandlerContext ctx, Object msg, ByteBuf out) throws Exception {
        byte[] bytes = JSON.toJSONString(msg).getBytes(StandardCharsets.UTF_8);
        out.writeBytes(bytes);
    }
}

io.netty.handler.codec.DecoderException: com.alibaba.fastjson.JSONException: unclosed str
    at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:98) ~[netty-codec-4.1.36.Final.jar:4.1.36.Final]
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:374) [netty-transport-4.1.36.Final.jar:4.1.36.Final]
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:360) [netty-transport-4.1.36.Final.jar:4.1.36.Final]
    at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:352) [netty-transport-4.1.36.Final.jar:4.1.36.Final]
    at io.netty.handler.timeout.IdleStateHandler.channelRead(IdleStateHandler.java:287) [netty-handler-4.1.36.Final.jar:4.1.36.Final]
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:374) [netty-transport-4.1.36.Final.jar:4.1.36.Final]
 

加载中
0
紫暘
紫暘

你是不是没有加粘包处理啊?我猜你是几个报名粘在一起了。

每串base64之间用什么判断他们分隔?没有的话,查查 LineBasedFrameDecoder 、 DelimiterBasedFrameDecoder 等等这些用于分割报文字节的类吧。

江火似流萤
江火似流萤
感谢帮助,确实是拆包导致的。
0
SpringBoot中文社区
SpringBoot中文社区

一般这种长连接,不会用来传文件。上传文件用http,返回文件的访问地址。把地址通过长连接发送过去。

你非要用netty传文件也肯定是可以的。约定好协议。例如,先传输文件名称,然后把文件分割成多少块儿,依次传输。传输完毕后,通过校验hash值来判断文件是否是完整。

江火似流萤
江火似流萤
谢谢帮助,我把上传模型改为下载,接收图片通过流传输。
0
lianjiao
lianjiao

更新fastjson到最新版 ,你这个应该是字符转义导致的错误。传文件你如果要加密依然可以针对byte数组采取加密,这里完全没必要base64,多一道手续,要知道json序列化是比较慢的,相对于socket的实时性来说。一般socket传输数据,我们用的是Google的ProtoBuf来作为数据交换格式,不会采用json,因为性能差。

再说了你传输文件干嘛不用专用的ftp呢?如果只是上传图片,也可以http的 multipart/form-data

江火似流萤
江火似流萤
感谢,我已经把fastjson升级最新版本,把base64改为byte[],之后发现无法解析json 找不到 json的后半部分,确认是拆包导致的,后来我就用了消息提解决了拆包问题,十分感谢,刚刚接触socket 后期优化会引入ProtoBuf。
0
E
Evian_Tian

这问题我处理过,就是tcp粘包或半包导致的,跟json解析包没有关系,建议用StringDecoder作为解码器,然后再hander里处理字符串,以{开始}结尾,找到一个{...}就视为要json处理

江火似流萤
江火似流萤
感谢帮助,确实跟json包没有关系 主要是解码的问题
返回顶部
顶部