socket中,大家是怎么定义数据包的? 定长数据? 还是结束符?

dos5gw 2012-02-10 09:06:19
加精
经大家谈一些经验性的问题, 之前的项目中, 我们一般都是采用发送定长数据的方法, 就是把"长度"放在包头里, recv到数据时, 先解析出包头里存储的"长度", 然后根据这个长度进行"粘包",
一般数据量不大的情况下, 这个方法是没有问题的,
但是, 如果在其他情况下, 这种方法是否稳定和可靠?

你们都是用的那种方法呢? 是定长数据? 还是靠结束符判断?
还有个问题, 如果用结束符判断(比如约定0x35是结束符), 那么应如何区分包中的0x35到底是结束符还是一般数据呢?

...全文
124141 308 打赏 收藏 举报
写回复
308 条回复
切换为时间正序
当前发帖距今超过3年,不再开放新的回复
发表回复
我爱大家369 2014-10-08
引用 22 楼 qq120848369 的回复:
头和尾基本用来做校验, 不是拿来做边界的.

头+类型+长度+数据+尾, 这种结构就可以.

拆包就是: 检验头, 然后拆出类型+长度, 然后根据长度拆数据, 然后检验尾巴.

  • 打赏
  • 举报
回复 1
wubicheng 2014-09-17
又看到了赵大神,Mark一个,目前正打算学socket编程,等看了书再回头来观摩大神。
  • 打赏
  • 举报
回复
赵4老师 2014-08-22
下一个包粘到本包后面(属正常现象)
  • 打赏
  • 举报
回复
twoweiaini 2014-08-22
引用 317 楼 zhao4zhong1 的回复:
[quote=引用 316 楼 twoweiaini 的回复:] [quote=引用 315 楼 zhao4zhong1 的回复:] [quote=引用 314 楼 twoweiaini 的回复:] [quote=引用 313 楼 zhao4zhong1 的回复:] [quote=引用 312 楼 twoweiaini 的回复:] 拿起尘封好多年的账号询问下,请各位大神,小神告知,问题如下: socket长连接情况: 1:内容变长,消息前4字节为内容长度,无结束符。那么当客户端传了一个内容长度小于头定义长度的包后。那么服务端之后所有消息均为垃圾消息,因为无法再次正确定位消息头。我这样理解对么?如何避免?或者是无解? 2:带终止符的,如何避免消息中包含终止符导致消息截取错误?我想了好久,好像不可能避免啊。。。 谁能解答下,谢谢。
在前面我的回帖里面这些问题都已经回答的很清楚了。[/quote] 大神,麻烦直接回答下呗,或者告诉我几楼。多谢啊。。。[/quote] 104楼和163楼 勤人是懒人的奴隶! [/quote] 谢谢,但是又想到个问题,如下: 比如客户端某次传来消息,包头定义包体长度应该为10,可包体长度却是20(假设某次代码级异常导致)。 这样会导致之后所有的消息均错误读取包头位置。(把上次的消息内容当消息头读取)。 请问这种情况在无终止符设计时如何处理?无解么? [/quote] 比如客户端某次传来消息,包头定义包体长度应该为10,可包体长度却是20(假设某次代码级异常或下一个包粘到本包后面(属正常现象)导致)。 将后面多余出来的10个字节作为后续新包头解析。 [/quote] 将后面多余出来的10个字节作为后续新包头解析。 那这样的话,将本不是包头的字节当包头解析肯定是错误的。 也就是在错包后的所有包均无法正确解析,此连接也就废掉了。 那结论如下: 1:当包协议定义为无终止符情况下,如果一旦发生长度不一致的错包,就无法程序自动纠错,只能人为发现修改程序后再次连接操作。 2:当包协议定义为有终止符情况下,除非连接两端增加转码或对终止符替换等操作外,否则会出现终止符不唯一的情况,也会导致部分包无法正确解析。 那这样看来,有终止符的貌似好一些,不会发生一个错包导致后续全部失效的情况。
  • 打赏
  • 举报
回复
eeeeelin 2014-08-20
mark下,以后学着点
  • 打赏
  • 举报
回复
阿呆_ 2014-08-20
又埋进去一堆? 3年后再来挖坟
  • 打赏
  • 举报
回复
赵4老师 2014-08-20
引用 316 楼 twoweiaini 的回复:
[quote=引用 315 楼 zhao4zhong1 的回复:] [quote=引用 314 楼 twoweiaini 的回复:] [quote=引用 313 楼 zhao4zhong1 的回复:] [quote=引用 312 楼 twoweiaini 的回复:] 拿起尘封好多年的账号询问下,请各位大神,小神告知,问题如下: socket长连接情况: 1:内容变长,消息前4字节为内容长度,无结束符。那么当客户端传了一个内容长度小于头定义长度的包后。那么服务端之后所有消息均为垃圾消息,因为无法再次正确定位消息头。我这样理解对么?如何避免?或者是无解? 2:带终止符的,如何避免消息中包含终止符导致消息截取错误?我想了好久,好像不可能避免啊。。。 谁能解答下,谢谢。
在前面我的回帖里面这些问题都已经回答的很清楚了。[/quote] 大神,麻烦直接回答下呗,或者告诉我几楼。多谢啊。。。[/quote] 104楼和163楼 勤人是懒人的奴隶! [/quote] 谢谢,但是又想到个问题,如下: 比如客户端某次传来消息,包头定义包体长度应该为10,可包体长度却是20(假设某次代码级异常导致)。 这样会导致之后所有的消息均错误读取包头位置。(把上次的消息内容当消息头读取)。 请问这种情况在无终止符设计时如何处理?无解么? [/quote] 比如客户端某次传来消息,包头定义包体长度应该为10,可包体长度却是20(假设某次代码级异常或下一个包粘到本包后面(属正常现象)导致)。 将后面多余出来的10个字节作为后续新包头解析。
  • 打赏
  • 举报
回复
twoweiaini 2014-08-20
引用 315 楼 zhao4zhong1 的回复:
[quote=引用 314 楼 twoweiaini 的回复:] [quote=引用 313 楼 zhao4zhong1 的回复:] [quote=引用 312 楼 twoweiaini 的回复:] 拿起尘封好多年的账号询问下,请各位大神,小神告知,问题如下: socket长连接情况: 1:内容变长,消息前4字节为内容长度,无结束符。那么当客户端传了一个内容长度小于头定义长度的包后。那么服务端之后所有消息均为垃圾消息,因为无法再次正确定位消息头。我这样理解对么?如何避免?或者是无解? 2:带终止符的,如何避免消息中包含终止符导致消息截取错误?我想了好久,好像不可能避免啊。。。 谁能解答下,谢谢。
在前面我的回帖里面这些问题都已经回答的很清楚了。[/quote] 大神,麻烦直接回答下呗,或者告诉我几楼。多谢啊。。。[/quote] 104楼和163楼 勤人是懒人的奴隶! [/quote] 谢谢,但是又想到个问题,如下: 比如客户端某次传来消息,包头定义包体长度应该为10,可包体长度却是20(假设某次代码级异常导致)。 这样会导致之后所有的消息均错误读取包头位置。(把上次的消息内容当消息头读取)。 请问这种情况在无终止符设计时如何处理?无解么?
  • 打赏
  • 举报
回复
赵4老师 2014-08-20
引用 314 楼 twoweiaini 的回复:
[quote=引用 313 楼 zhao4zhong1 的回复:] [quote=引用 312 楼 twoweiaini 的回复:] 拿起尘封好多年的账号询问下,请各位大神,小神告知,问题如下: socket长连接情况: 1:内容变长,消息前4字节为内容长度,无结束符。那么当客户端传了一个内容长度小于头定义长度的包后。那么服务端之后所有消息均为垃圾消息,因为无法再次正确定位消息头。我这样理解对么?如何避免?或者是无解? 2:带终止符的,如何避免消息中包含终止符导致消息截取错误?我想了好久,好像不可能避免啊。。。 谁能解答下,谢谢。
在前面我的回帖里面这些问题都已经回答的很清楚了。[/quote] 大神,麻烦直接回答下呗,或者告诉我几楼。多谢啊。。。[/quote] 104楼和163楼 勤人是懒人的奴隶!
  • 打赏
  • 举报
回复
twoweiaini 2014-08-20
引用 313 楼 zhao4zhong1 的回复:
[quote=引用 312 楼 twoweiaini 的回复:] 拿起尘封好多年的账号询问下,请各位大神,小神告知,问题如下: socket长连接情况: 1:内容变长,消息前4字节为内容长度,无结束符。那么当客户端传了一个内容长度小于头定义长度的包后。那么服务端之后所有消息均为垃圾消息,因为无法再次正确定位消息头。我这样理解对么?如何避免?或者是无解? 2:带终止符的,如何避免消息中包含终止符导致消息截取错误?我想了好久,好像不可能避免啊。。。 谁能解答下,谢谢。
在前面我的回帖里面这些问题都已经回答的很清楚了。[/quote] 大神,麻烦直接回答下呗,或者告诉我几楼。多谢啊。。。
  • 打赏
  • 举报
回复
赵4老师 2014-08-20
引用 312 楼 twoweiaini 的回复:
拿起尘封好多年的账号询问下,请各位大神,小神告知,问题如下: socket长连接情况: 1:内容变长,消息前4字节为内容长度,无结束符。那么当客户端传了一个内容长度小于头定义长度的包后。那么服务端之后所有消息均为垃圾消息,因为无法再次正确定位消息头。我这样理解对么?如何避免?或者是无解? 2:带终止符的,如何避免消息中包含终止符导致消息截取错误?我想了好久,好像不可能避免啊。。。 谁能解答下,谢谢。
在前面我的回帖里面这些问题都已经回答的很清楚了。
  • 打赏
  • 举报
回复
twoweiaini 2014-08-20
拿起尘封好多年的账号询问下,请各位大神,小神告知,问题如下: socket长连接情况: 1:内容变长,消息前4字节为内容长度,无结束符。那么当客户端传了一个内容长度小于头定义长度的包后。那么服务端之后所有消息均为垃圾消息,因为无法再次正确定位消息头。我这样理解对么?如何避免?或者是无解? 2:带终止符的,如何避免消息中包含终止符导致消息截取错误?我想了好久,好像不可能避免啊。。。 谁能解答下,谢谢。
  • 打赏
  • 举报
回复
随风遁隐 2014-08-19
引用 282 楼 pkgogai 的回复:
本来是想百度一下,TCP的可靠性是到哪种程度,在传输过程中数据的内容或长度有没有可能出错,结果找到了这个帖子,找到了我想要的结果,不管是意外还是人为,数据的内容是可能出错的。 然后我又怀着看热闹的心情,花了2个小时从头到尾的看完了这长达两年的帖子。 发现这帖子里有意思的地方太多了,果然以前很少灌论坛是我的损失呀。 首先LZ的问题很单纯,对于粘包情况,是记录长度拆分好呢,还是按特定分隔符来拆分好。 1楼、2楼的回答,通常是用固定长度,或者记录长度 3楼就问,结束符的判断不受欢迎?以前的老代码用过结束符,其中难道有什么玄机 接着zhao4zhong1(因为处于浪尖上所以提名字)就给出个简单的方法base64,将二进制数据流转化成文本来,然后用'\0'作为结束符,也就是要将二进制流中的'\0'转译掉,又懒得自己写代码,所以用了现成的base64,虽然很浪费资源,但也凑合着可以用。 单到这点上,还是个很好的答案的。 不过接下来的问题就奇怪了,zhao4zhong1竟然奇怪的问了用包头加包体几个问题。一下子引得无数人进攻。然后就是口水了。 其实我也搞不明白,为什么说完用分隔符后,却要来问包头加包体这几个问题,明明都是一样的。 1、仅收到一个字节时怎么办。 :你用base64时仅收到一个字母而没有受到'\0'时怎么办? 你怎么办这里就怎么办 2、收到两个字节的包头比如FF FF(表示后续包体长度为65535,或者包头+包体长度65535即后续包体长度65533),但后续收到数据长度迟迟达不到要求怎么办? :你用base64时一直收到字母和数字,就是收不到'\0'时怎么办? 你怎么办这里就怎么办 3、比如约定每个包最大长度为0x1000,但收到的包头中长度超过0x1000怎么办? :base64中可能出现的字符范围是固定的,但收到的数据里有超过范围的字符怎么办?比如收到个值为00000001的字节 对于这种数据出错的情况,你怎么办的这里就这么办 4、应用需要发送超过65535个字节的包怎么办 :base64的字符只有64种来表示数据,对于一个值>64的字节要怎么表示? base64可以把数据分成很多个字符来表示,这里为什么就不能把大数据分成很多个包后再传? ……………………………… 接下来大多都是无谓的口水了(我板凳看了2小时的热闹) ……………………………… 还是回到LZ这个很单纯的问题上来吧,是记录长度拆分好呢,还是按特定分隔符来拆分好? 从计算机逻辑上来讲,其实没什么区别,都是要有校验有分割,而从人的思维逻辑上讲,我还是喜欢记录长度的方式。 因为如果用分隔符,就要对每个字节都进行转译,发送前转译,收到后还要转译回来,虽然对于编程来说,就是一个简单的循环语句,但在心理上,却有一种对所有数据都要进行变换的这种很麻烦的感觉。而按长度来,只要处理少数几个字节,真正的数据体是原样copy的,虽然从编程语句上来说没什么变化,但从心理上,却有一种数据就是原样搬来搬去,这样清爽的感觉。 所以,我建议大家用长度。qq120848369在22楼说的就是大众格式,LZ在26楼也赞同了。 --------原文: 头和尾基本用来做校验, 不是拿来做边界的. 头+类型+长度+数据+尾, 这种结构就可以. 拆包就是: 检验头, 然后拆出类型+长度, 然后根据长度拆数据, 然后检验尾巴. ---------------------- 顺便再啰嗦一下,我自己现在这个应用中,只传输控制命令,而且是加密成128字节的数据段,加解密的算法也是自己写的,本身就有校验,上层逻辑还有数据是否合法的判断,所以在网络这块什么多余的都不用考虑,就一次128字节的收发,超时设为10秒,有错就重来,连错3次就重连,连续3次重连就拒绝此IP五分钟,逻辑上单纯又直白。
顶一个。。
  • 打赏
  • 举报
回复
赵4老师 2014-08-19
引用 310 楼 kinwyb 的回复:
[quote=引用 282 楼 pkgogai 的回复:] 本来是想百度一下,TCP的可靠性是到哪种程度,在传输过程中数据的内容或长度有没有可能出错,结果找到了这个帖子,找到了我想要的结果,不管是意外还是人为,数据的内容是可能出错的。 然后我又怀着看热闹的心情,花了2个小时从头到尾的看完了这长达两年的帖子。 发现这帖子里有意思的地方太多了,果然以前很少灌论坛是我的损失呀。 首先LZ的问题很单纯,对于粘包情况,是记录长度拆分好呢,还是按特定分隔符来拆分好。 1楼、2楼的回答,通常是用固定长度,或者记录长度 3楼就问,结束符的判断不受欢迎?以前的老代码用过结束符,其中难道有什么玄机 接着zhao4zhong1(因为处于浪尖上所以提名字)就给出个简单的方法base64,将二进制数据流转化成文本来,然后用'\0'作为结束符,也就是要将二进制流中的'\0'转译掉,又懒得自己写代码,所以用了现成的base64,虽然很浪费资源,但也凑合着可以用。 单到这点上,还是个很好的答案的。 不过接下来的问题就奇怪了,zhao4zhong1竟然奇怪的问了用包头加包体几个问题。一下子引得无数人进攻。然后就是口水了。 其实我也搞不明白,为什么说完用分隔符后,却要来问包头加包体这几个问题,明明都是一样的。 1、仅收到一个字节时怎么办。 :你用base64时仅收到一个字母而没有受到'\0'时怎么办? 你怎么办这里就怎么办 2、收到两个字节的包头比如FF FF(表示后续包体长度为65535,或者包头+包体长度65535即后续包体长度65533),但后续收到数据长度迟迟达不到要求怎么办? :你用base64时一直收到字母和数字,就是收不到'\0'时怎么办? 你怎么办这里就怎么办 3、比如约定每个包最大长度为0x1000,但收到的包头中长度超过0x1000怎么办? :base64中可能出现的字符范围是固定的,但收到的数据里有超过范围的字符怎么办?比如收到个值为00000001的字节 对于这种数据出错的情况,你怎么办的这里就这么办 4、应用需要发送超过65535个字节的包怎么办 :base64的字符只有64种来表示数据,对于一个值>64的字节要怎么表示? base64可以把数据分成很多个字符来表示,这里为什么就不能把大数据分成很多个包后再传? ……………………………… 接下来大多都是无谓的口水了(我板凳看了2小时的热闹) ……………………………… 还是回到LZ这个很单纯的问题上来吧,是记录长度拆分好呢,还是按特定分隔符来拆分好? 从计算机逻辑上来讲,其实没什么区别,都是要有校验有分割,而从人的思维逻辑上讲,我还是喜欢记录长度的方式。 因为如果用分隔符,就要对每个字节都进行转译,发送前转译,收到后还要转译回来,虽然对于编程来说,就是一个简单的循环语句,但在心理上,却有一种对所有数据都要进行变换的这种很麻烦的感觉。而按长度来,只要处理少数几个字节,真正的数据体是原样copy的,虽然从编程语句上来说没什么变化,但从心理上,却有一种数据就是原样搬来搬去,这样清爽的感觉。 所以,我建议大家用长度。qq120848369在22楼说的就是大众格式,LZ在26楼也赞同了。 --------原文: 头和尾基本用来做校验, 不是拿来做边界的. 头+类型+长度+数据+尾, 这种结构就可以. 拆包就是: 检验头, 然后拆出类型+长度, 然后根据长度拆数据, 然后检验尾巴. ---------------------- 顺便再啰嗦一下,我自己现在这个应用中,只传输控制命令,而且是加密成128字节的数据段,加解密的算法也是自己写的,本身就有校验,上层逻辑还有数据是否合法的判断,所以在网络这块什么多余的都不用考虑,就一次128字节的收发,超时设为10秒,有错就重来,连错3次就重连,连续3次重连就拒绝此IP五分钟,逻辑上单纯又直白。
顶一个。。[/quote] 顶“照一个不存在的葫芦画瓢,照一个不存在的猫画虎”一个?!
  • 打赏
  • 举报
回复
hanger1212 2014-08-13
收藏=======
  • 打赏
  • 举报
回复
排山和倒海 2014-08-12
包头+包尾的方式吧
  • 打赏
  • 举报
回复
bobo_包子 2014-08-12
试试protobuf吧 http://blog.csdn.net/program_think/article/details/4229773
  • 打赏
  • 举报
回复
xiaohuh421 2014-08-12
包起始标记+包长度+数据内容+包结束标记
  • 打赏
  • 举报
回复
定长,提前定义好结构体,比如同步头(识别数据帧的开始),帧头,要传输数据等,因为结构体的大小是提前知道的,所以在接收后可以strcpy来取各个位置上的数据.
  • 打赏
  • 举报
回复
赵4老师 2014-08-11
引用 301 楼 xmisgenius 的回复:
有没有总结一下的
实践出真知!
  • 打赏
  • 举报
回复
加载更多回复(288)
相关推荐
发帖
C++ 语言

6.2w+

社区成员

C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
帖子事件
创建了帖子
2012-02-10 09:06
社区公告
暂无公告