首页   注册   登录
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
宝塔
V2EX  ›  Java

Java TCP 校验问题,求助

  •  
  •   tearslee · 270 天前 · 1557 次点击
    这是一个创建于 270 天前的主题,其中的信息可能已经有所发展或是发生改变。

    协议格式:

    1.uint16 消息长度 msgLen,下面的 2,3,4 的总 byte 长度,不包括 msgLen 本身,2,3,4 统称为 msgData

    2.uint8 校验字段,算法如下:

    发送的时候:

    	var cbCheckCode byte=0
    	for i = 1; i < msgLen; i++ {
    		cbCheckCode += msgData[i]
    	}
    	result = ^cbCheckCode + 1//然后把结果 result 写入 uint8 校验字段 msgData[0]
    

    接收的时候:

    var cbCheckCode byte=msgData[0]
    for i = 1; i < msgLen; i++ {
    	cbCheckCode += msgData[i]
    }
    if 0 != cbCheckCode {
    	return//校验结果有误,报错
    }
    

    消息数据:

    3.uint32 消息号:uint32(mainCmdID) | uint32(subCmdID)<<16,mainCmdID (主消息号)和 subCmdID (子消息号)都是 uint16

    4.byte 字节流,消息数据 data,一般是 struct 的结构体数据转换成字节流,到时候看具体用到的数据类型再说怎么转换,比如 string 类型,转换成字节流的话,前面 2 个字节表示长度,后面的就是 string 的内容

    20 回复  |  直到 2019-02-25 21:21:14 +08:00
        1
    tearslee   270 天前
    我是做 javaWeb 的,对于校验 tcp 校验不是很明白,请教一下各位,我该如何写编解码器?
        2
    xzg   270 天前
    这是 java ?这是 go 的代码吧。还有计算 cbCheckCode 又放到 msgData[0]里看不懂。我觉得如果校验发送数据可以用 bcc 校验码添加到字节流的末尾,接收数据再取末尾校验。
        3
    coolcfan   270 天前
    发送 /接受的格式是别人定义的还是需要自己定义?

    如果是别人定义的,那自己画个图把数据包格式画出来,程序里按顺序读写就行了……
        4
    SilentHill   270 天前
    没看懂啊。。这和 tcp 有啥关系?而且你做 web 的,还有自己代码接收网络数据的需求?
    而且 java 没有 struct 啊,这语法看着也不像 java。
    如果自己定义数据格式,那么对于服务端,就一直尝试读取期望的字节大小,读到报文头后,解析出来,得到数据长度后,在继续读取期望的大小,多余的丢掉,最后反序列化为内部可识别的结构体或者类。。

    至于序列化和反序列化,为什么不用已经很成熟的 google protobuf,而自己去编解码呢。。
        5
    tearslee   270 天前
    @SilentHill 就是 socket 通信问题,我的后台与服务器需要使用 socket 通信, 协议是对方定义的,我需要对接.
        6
    tearslee   270 天前
    @xzg 是的,这是对方写的伪代码,是 go 的 是如何校验对方的发包
        7
    tearslee   270 天前
    @coolcfan 是对方定义的,但是我不会读取...对于如何正确读取并校验,我很迷茫
        8
    SilentHill   270 天前
    @tearslee

    那就是 socket 编程喽,其实这个网上还是挺多的,基本代码样例都差不多。和我上面说的差不多,因为报文格式和大小都是严格确定的,所以在服务端一直读到期望的大小再进行反序列化,具体可以在网上找找,这里一言两句说不清的,而且你这个也不是 java
        9
    coolcfan   270 天前   ♥ 1
    @tearslee #7

    先把格式画出来嘛,

    | length: 2 | checksum: 1 | id: 4 | payload: [ length: 2 | content: length ] |

    按照顺序把 byte 读进来就行了,你把除了“ content ”的部分都当作 header,相当于 header 一共 9 个 byte,后面读多少按照 header 提供的信息去读
        10
    tearslee   270 天前
    @coolcfan 谢谢,这个思路我会尝试的
        11
    buliugu   270 天前
    如果使用 netty,请看一下 Decoder
        12
    tearslee   270 天前
    @buliugu 我这边只是客户端,不使用 netty
        13
    honeycomb   270 天前 via Android
    @tearslee 比较笨但也简单的一个办法是用 netty 的套路写收发消息的组件,然后自己做一个 Decoder 的实现,它给的输入直接包装成了 netty 的 ByteBuf,这东西比 Java 自己的 ByteBuffer 好用。

    之后校验,反序列化(到一个 Java pojo )都能轻松地在里面做了。
        14
    honeycomb   270 天前 via Android
    @tearslee 客户端的话也可利用 netty 的 bytebuf 组件来简化处理 byte 数组
        15
    blackboom   270 天前
    没有仔细看,你的问题是什么呢,校验结果有误,报错?

    Netty io.netty.handler.codec.protobuf 包中有这么两个类
    ProtobufVarint32LengthFieldPrepender
    ProtobufVarint32FrameDecoder
        16
    rockyou12   270 天前   ♥ 1
    @tearslee 看下 java nio 包的 Buffer 及其子类就行了,不需要 netty 来读取数据。
        17
    tearslee   270 天前
    @rockyou12 明白你的意思了,感谢
        18
    ZiLong   270 天前
    还是要看你用的什么通信模型,bio/bio 及使用类库(jdk/netty/mina),调用相应读取接口
        19
    jitongxi   270 天前
    @tearslee netty 的 bytebuf 和 自带的 nio bytebuf 都可以操作.
        20
    jitongxi   270 天前
    @tearslee 再不济[]byte 都可以弄完
    关于   ·   FAQ   ·   API   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   1223 人在线   最高记录 5043   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.3 · 22ms · UTC 18:01 · PVG 02:01 · LAX 10:01 · JFK 13:01
    ♥ Do have faith in what you're doing.