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

Java TCP 校验问题,求助

  •  
  •   tearslee · 2019-02-25 10:48:52 +08:00 · 3114 次点击
    这是一个创建于 2101 天前的主题,其中的信息可能已经有所发展或是发生改变。

    协议格式:

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

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

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

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

    先把格式画出来嘛,

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

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

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

    Netty io.netty.handler.codec.protobuf 包中有这么两个类
    ProtobufVarint32LengthFieldPrepender
    ProtobufVarint32FrameDecoder
    rockyou12
        16
    rockyou12  
       2019-02-25 11:58:24 +08:00   ❤️ 1
    @tearslee 看下 java nio 包的 Buffer 及其子类就行了,不需要 netty 来读取数据。
    tearslee
        17
    tearslee  
    OP
       2019-02-25 14:09:03 +08:00
    @rockyou12 明白你的意思了,感谢
    ZiLong
        18
    ZiLong  
       2019-02-25 15:44:15 +08:00
    还是要看你用的什么通信模型,bio/bio 及使用类库(jdk/netty/mina),调用相应读取接口
    jitongxi
        19
    jitongxi  
       2019-02-25 21:20:54 +08:00
    @tearslee netty 的 bytebuf 和 自带的 nio bytebuf 都可以操作.
    jitongxi
        20
    jitongxi  
       2019-02-25 21:21:14 +08:00
    @tearslee 再不济[]byte 都可以弄完
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3332 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 12:23 · PVG 20:23 · LAX 04:23 · JFK 07:23
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.