Java TCP 校验问题,求助

2019-02-25 10:48:52 +08:00
 tearslee

协议格式:

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 的内容

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

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

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

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

先把格式画出来嘛,

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

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

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

Netty io.netty.handler.codec.protobuf 包中有这么两个类
ProtobufVarint32LengthFieldPrepender
ProtobufVarint32FrameDecoder
rockyou12
2019-02-25 11:58:24 +08:00
@tearslee 看下 java nio 包的 Buffer 及其子类就行了,不需要 netty 来读取数据。
tearslee
2019-02-25 14:09:03 +08:00
@rockyou12 明白你的意思了,感谢
ZiLong
2019-02-25 15:44:15 +08:00
还是要看你用的什么通信模型,bio/bio 及使用类库(jdk/netty/mina),调用相应读取接口
jitongxi
2019-02-25 21:20:54 +08:00
@tearslee netty 的 bytebuf 和 自带的 nio bytebuf 都可以操作.
jitongxi
2019-02-25 21:21:14 +08:00
@tearslee 再不济[]byte 都可以弄完

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/538364

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX