TCP收发怎么解决同步的问题

谁学逆向工程 2016-11-09 03:02:22
加精
我现在是电脑和安卓手机在局域网内收发信息,收发的内容是数据库表的字段。
电脑的代码是连续4个发送,手机的代码是4个连续的接收。那么问题来了,由于速度差异,电脑发送了3个之后,手机才开始第一次调用接收。这样手机就可能在第一次接收时把3个字段接收到第一个缓冲区去。
求个解决思路!
...全文
6496 48 打赏 收藏 转发到动态 举报
写回复
用AI写文章
48 条回复
切换为时间正序
请发表友善的回复…
发表回复
ccm1818168 2016-12-03
  • 打赏
  • 举报
回复
我是这样定义数据包的
7E len cmd data...data xor sum
每个包都是这样的格式
所以不管每次接收到的包是否完整或有多余,都容易处理。
因TCP与UDP的特性不同,后者处理时会麻烦点。
谁学逆向工程 2016-12-01
  • 打赏
  • 举报
回复
引用 46 楼 mf19870602 的回复:
你这个是数据粘包哇。 你应该定义通信的报文,也就是你的应用协议
问题是这里面不全是字符串,还有图片,图片格式化成字节序列之后有可能和自己的包头包尾发生重复,怎么办?
毛员外 2016-11-30
  • 打赏
  • 举报
回复
你这个是数据粘包哇。 你应该定义通信的报文,也就是你的应用协议 比如报文:****message#### ****就是包头 ####就是包尾 比如你发了如下数据给客户端: ****1234567####****1234567####****1234567####****1234567#### 客户端一次一次的读取数据: 第一次读取到数据:****1234567####****1234(此时读取到了一包半的数据,粘包了,你得拆) 第二次读取到数据:567####****123 第三次读取到数据:4567####****1234567#### 你得把接收到的数据按照你定义的报文****message####来拆分 比如第一次读取的数据:首先将完整包****1234567####取出来,剩下的****1234放在缓存中,等待第二次出去数据,把剩下数据和第二次的数据合并****1234567####****123,然后在拆,当然这是最笨的方法,这里可以优化的,但是意思大概就是这个意思
太上绝情 2016-11-30
  • 打赏
  • 举报
回复
这个问题叫粘包问题,是tcp开发中非常常见的问题,但是国内的技术资料中都对此语焉不详。解决方法就是上面有人提到的自定义协议头,并在协议头中发送长度,只有接收到了足够的长度的数据后才转入业务逻辑处理层。
qq_36878415 2016-11-30
  • 打赏
  • 举报
回复
先了解TPL协议
qq_36878415 2016-11-30
  • 打赏
  • 举报
回复
先了解TPL协议
谁学逆向工程 2016-11-28
  • 打赏
  • 举报
回复
引用 40 楼 zhblue 的回复:
我以为已经讲的够清楚了,没想到再来还在讨论。
C#和安卓都可以吗,最近在忙别的,没时间验证。我这个是C#和安卓通信的
歪嘴鱼 2016-11-28
  • 打赏
  • 举报
回复
引用 41 楼 xiaoyuanyuan2009 的回复:
[quote=引用 40 楼 zhblue 的回复:] 我以为已经讲的够清楚了,没想到再来还在讨论。
C#和安卓都可以吗,最近在忙别的,没时间验证。我这个是C#和安卓通信的[/quote] 基本所有语言的TCP栈都有,因为这是协议里定的。 可能有的嵌入式系统里会缺少吧,不过越是嵌入式越需要这个,应该不会不支持。
xengine-qyt 2016-11-27
  • 打赏
  • 举报
回复
自定义协议头+长度来解决,我就是这样做的,TCP就是这样的 别想了
歪嘴鱼 2016-11-27
  • 打赏
  • 举报
回复
我以为已经讲的够清楚了,没想到再来还在讨论。 TCP连接有个选项no_delay选项,你只要在socket创建连接后激活这个选项 try { socket.setTcpNoDelay(true); } catch (SocketException e) { // TODO Auto-generated catch block e.printStackTrace(); } 就是1字节数据也是可以即时发送过去的。
Frank6600 2016-11-26
  • 打赏
  • 举报
回复
引用 37 楼 xiaoyuanyuan2009 的回复:
[quote=引用 36 楼 frank_lee_cn 的回复:] 用while回圈收,直到收齐你要的数量。(除非超时)
读取函数有个参数,就是“希望读取多少字节”,假设我希望读1024字节,但对方第一次没发这么多,我会不会读很多垃圾字节[/quote] 不会
谁学逆向工程 2016-11-26
  • 打赏
  • 举报
回复
引用 36 楼 frank_lee_cn 的回复:
用while回圈收,直到收齐你要的数量。(除非超时)
读取函数有个参数,就是“希望读取多少字节”,假设我希望读1024字节,但对方第一次没发这么多,我会不会读很多垃圾字节
Frank6600 2016-11-26
  • 打赏
  • 举报
回复
引用 35 楼 xiaoyuanyuan2009 的回复:
[quote=引用 33 楼 frank_lee_cn 的回复:] 因为有几点是你没想到的: 1.TCP协议保证会把客户端发送的一定会发过来
1.发送端会不会一次发不完, 2.如果只发了一部分的时候,接收端是不是就已经可以读取了, 3.接收端是不是要等发送端全部发送完毕以后在读取?[/quote] 1.不保证一次发完,所以上面说了,用while回圈收,直到收齐你要的数量。(除非超时) 2.是,读取即可。 3.不用。 用while回圈收,直到收齐你要的数量。(除非超时)
谁学逆向工程 2016-11-26
  • 打赏
  • 举报
回复
引用 33 楼 frank_lee_cn 的回复:
因为有几点是你没想到的: 1.TCP协议保证会把客户端发送的一定会发过来
发送端会不会一次发不完,如果只发了一部分的时候,接收端是不是就已经可以读取了,接收端是不是要等发送端全部发送完毕以后在读取?
谁学逆向工程 2016-11-25
  • 打赏
  • 举报
回复
引用 25 楼 frank_lee_cn 的回复:
等到4个都收到。
怎么确定对方4个字节发完了,读取缓冲区的时候要提供个“我想读多少”的参数
Frank6600 2016-11-25
  • 打赏
  • 举报
回复
对了。补充一句 除了“数据长度+数据"这个方案外, 还有一个方案是用分隔符(比如0x13)分段, SMTP, POP3或http(事实上它两种方案都支持)协议都用这个方案。
Frank6600 2016-11-25
  • 打赏
  • 举报
回复
引用 32 楼 xiaoyuanyuan2009 的回复:
[quote=引用 25 楼 frank_lee_cn 的回复:] 等到4个都收到。
假设包头用int 4字节,长度用int4字节,一共8字节。如果对方发送的内容少于8字节,接收端也发现不了啊 怎么确定对方4个字节发完了,读取缓冲区的时候要提供个“我想读多少”的参数[/quote] 你这么想是没有必要的。 你仔细看看大家的回答,答案都是一样的。 想过为什么吗? 因为有几点是你没想到的: 1.TCP协议保证会把客户端发送的一定会发过来 2.服务端收数据时,可以设置超时。超时没收到,就结束自己读数据的线程就行了。 所以你只要用byte[4]读四个字节,然后解码这4字节为long, 然后用这long值读后续数据即可。 至于读后续数据,用一个固定长度的bytes,比如byte[256]或byte[8192]去读即可。 你或许会问,万一long值大于8192呢? 答案是多读几次直到达到long值的数据。 如果以上条件不满足,超时就结束自己线程,这样就行了。 其他的,交给客户端去配合。 任何原因的不配合,比如客户端不按规则玩,或者网络断了,或者任何我们没料到的, 超时就结束自己线程,这样就行了。 剩余的,你不要坐在这里钻牛角尖的乱想,你多写几个例子,就明白了。
谁学逆向工程 2016-11-24
  • 打赏
  • 举报
回复
引用 30 楼 Sevk 的回复:
每个TCP包加个包头和长度,就容易组装了。通讯协议定好。
假设包头用int 4字节,长度用int4字节,一共8字节。如果对方发送的内容少于8字节,接收端也发现不了啊
sevk 2016-11-24
  • 打赏
  • 举报
回复
每个TCP包加个包头和长度,就容易组装了。通讯协议定好。
谁学逆向工程 2016-11-22
  • 打赏
  • 举报
回复
引用 28 楼 linux_hacher 的回复:
同上~可以模仿TCP协议的机制来解决这个问题啊~
啥机制
加载更多回复(26)

62,614

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧