tearslee
V2EX  ›  Java

Java TCP 校验问题,求助

  •  
  •   tearslee · Feb 25, 2019 · 4386 views
    This topic created in 2819 days ago, the information mentioned may be changed or developed.

    协议格式:

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

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

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

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

    先把格式画出来嘛,

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

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

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

    Netty io.netty.handler.codec.protobuf 包中有这么两个类
    ProtobufVarint32LengthFieldPrepender
    ProtobufVarint32FrameDecoder
    rockyou12
    rockyou12
    Feb 25, 2019❤️1
    16
    @tearslee 看下 java nio 包的 Buffer 及其子类就行了,不需要 netty 来读取数据。
    tearslee
    tearslee
    OP
    Feb 25, 2019
    17
    @rockyou12 明白你的意思了,感谢
    ZiLong
    ZiLong
    Feb 25, 2019
    18
    还是要看你用的什么通信模型,bio/bio 及使用类库(jdk/netty/mina),调用相应读取接口
    jitongxi
    jitongxi
    Feb 25, 2019
    19
    @tearslee netty 的 bytebuf 和 自带的 nio bytebuf 都可以操作.
    jitongxi
    jitongxi
    Feb 25, 2019
    20
    @tearslee 再不济[]byte 都可以弄完
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Privacy   ·   Solana   ·   2132 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 38ms · UTC 08:14 · PVG 16:14 · LAX 00:14 · JFK 03:14
    ♥ Do have faith in what you're doing.