网络传输中,客户端如何处理大量的数据接收?

tingsky 2011-08-26 11:26:31
服务器快速向客户端发送不同长度的数据块(长度在80Byte--300Byte不等),因客户端无法快速接
收每次的数据块造成接收缓冲区的累积。当客户端每次按1024Byte从Socket缓冲区获得数据时就会
将下次的数据块截断,造成下次读取的数据块异常而带来程序的异常。
我想请教大家,网络传输中,一般是如何处理大量不同长度的数据块?
谢谢大家。
...全文
489 19 打赏 收藏 转发到动态 举报
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
tingsky 2011-08-29
  • 打赏
  • 举报
回复
[Quote=引用 18 楼 lijianli9 的回复:]

开一个线程,读取socket数据,数据包含包头+包体。另外的线程读取缓存到队列中的数据进行处理。
[/Quote]
正有此意,Thx~
lijianli9 2011-08-27
  • 打赏
  • 举报
回复
开一个线程,读取socket数据,数据包含包头+包体。另外的线程读取缓存到队列中的数据进行处理。
tingsky 2011-08-27
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 yynetsdk 的回复:]

客户端如果缓冲区满了,造成的异常,我想客户端的代码是没法解决了,要从 服务器设计上入手了。

1.增加双方得校验code

2.服务器做队列,顺序发送
[/Quote]
这方式确实可以保证数据的可靠传输,但效率要下降。

-------------------------------------------------------------
接下来我描述下,我将使用的方式:
对于半包问题,我将采用数据块拼接来解决。
同时,我将建立两个缓冲池用于暂存Socket接收到的数据,一是缓冲区用于保存一般数据,另一个缓冲区用于紧急数据(避免紧急信息不及时),应用模块通过从缓冲池取数据来处理。
这样的处理方式是将接受模块与数据的应用分离,保证Socket的快速接收,避免累积,如果有累积,则通过数据块拼接完成。

如果我没有描述清楚,请告诉我。
tingsky 2011-08-26
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 ouyh12345 的回复:]

自定义协议,在头里,指明数据长度
[/Quote]
目前,每个数据块都有值保存当前数据块的长度。但,目前问题在于,当Socket的接收缓冲区累积了很多个数据块,每次获取固定长度的话有可能将末端的节点数据截断使得下次获取的内容不完成。
比如有这样一串数据在缓冲区中(数字表示长度,‘b’表示内容):
2bb3bbb6bbbbbb2bb
现在从接收缓冲区获取 10字符:
2bb3bbb6bb
剩余的字符:
bbbb2bb
这样下次获取的数据是不完整的,我又无法判断,第一个字符是长度还是数据,每个数据块没有一个开头的标识。

-------------------------------------------------------------
另:
如果,我的接收端,读取Socket缓冲区的数据没有延时的话,是不是不会出现缓冲区的累积,可以达到对方发送一次数据,我就能接受到一次数据?

谢谢 ouyh12345 和 ttktw 的回复。
ttktw 2011-08-26
  • 打赏
  • 举报
回复
我一般这样处理:
服务器发送数据块前发送数据块长度,然后发送数据
客户端先读取这个长度,然后按这个长度接收数据。
ouyh12345 2011-08-26
  • 打赏
  • 举报
回复
自定义协议,在头里,指明数据长度
羽飞 2011-08-26
  • 打赏
  • 举报
回复
自定数据类型,一般都是长度,类型,数据
接收的时候根据前两个字段对数据处理
  • 打赏
  • 举报
回复
自定义一个协议,先接头 再接数据
abxialiang 2011-08-26
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 yigerengudu 的回复:]
引用 1 楼 ouyh12345 的回复:

自定义协议,在头里,指明数据长度

目前,每个数据块都有值保存当前数据块的长度。但,目前问题在于,当Socket的接收缓冲区累积了很多个数据块,每次获取固定长度的话有可能将末端的节点数据截断使得下次获取的内容不完成。
比如有这样一串数据在缓冲区中(数字表示长度,‘b’表示内容):
2bb3bbb6bbbbbb2bb
现在从接收缓冲区获取 ……
[/Quote]

好,你读了10个字节,前面的几个包没问题,但是bbbb2bb前面的6bb明显不是一个完整的包,所以你要先留着6bb再与bbbb2bb连接,然后再处理.

我是这么处理的,手动准备缓存区A(1024字节),读取网络数据到A(可能是3个半数据包)中,然后提取A中完整的数据包(3个),剩下的半个重新移动到A缓冲区的起始位置,然后再次读取网络数据填充A缓冲区.重复先前的处理.



yynetsdk 2011-08-26
  • 打赏
  • 举报
回复
客户端如果缓冲区满了,造成的异常,我想客户端的代码是没法解决了,要从 服务器设计上入手了。

1.增加双方得校验code

2.服务器做队列,顺序发送
xi52qian 2011-08-26
  • 打赏
  • 举报
回复
自己定义协议和包头包围格式,按包头中的数据长度来分包和接收大小。
协议定义收到包后要回复ACK才算接收完成再发下一个包。客户端同步来接收。
ttktw 2011-08-26
  • 打赏
  • 举报
回复
也可以说是消息边界问题,上网找找一般的处理方法吧
ttktw 2011-08-26
  • 打赏
  • 举报
回复
我只做过一些小项目,在局域网中,一般发送就能接收到

其实你用1楼的建议,就不需要考虑这个问题,管他缓冲区有多少,我只按长度接收这么多
tingsky 2011-08-26
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 chenjiawei007 的回复:]

拼接下数据包~

A为协议头,B为协议尾。

假设你的接受缓存区有三包数据A++++B A+++B A+++B

你取出的数据A++++B A+++

解析第一包数据,然后丢给应用层,你剩下A+++数据,放到临时缓存,等待下次取时把数据接上,解析。

就是一个半包的问题。其实根据业务不同有许多策略。
[/Quote]

Thx to chenjiawei007:
让我知道了这个问题的范畴:一个半包的问题。
tingsky 2011-08-26
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 ttktw 的回复:]

1.干嘛要先获取10字符?
这样接收:
2
bb
3
bbb
6
...
每次接收的数据,第一个字符是不是长度就知道了
2. 如果没有及时读取缓冲区数据,会出现累积;
在不存在网络延迟和及时接收的话,发送一次,就会接收一次
[/Quote]
to ttktw:
你提到的第二点:在不存在网络延迟和及时接收的话,发送一次,就会接收一次。
前提是“在不存在网络延迟和” 这个条件在局域网中容易实现吗?
chenjiawei007 2011-08-26
  • 打赏
  • 举报
回复
拼接下数据包~

A为协议头,B为协议尾。

假设你的接受缓存区有三包数据A++++B A+++B A+++B

你取出的数据A++++B A+++

解析第一包数据,然后丢给应用层,你剩下A+++数据,放到临时缓存,等待下次取时把数据接上,解析。

就是一个半包的问题。其实根据业务不同有许多策略。

ttktw 2011-08-26
  • 打赏
  • 举报
回复
在重叠IO模式下,缓冲区数据会由系统自动拷贝出来,以便接收新的数据
ttktw 2011-08-26
  • 打赏
  • 举报
回复
1.干嘛要先获取10字符?
这样接收:
2
bb
3
bbb
6
...
每次接收的数据,第一个字符是不是长度就知道了
2. 如果没有及时读取缓冲区数据,会出现累积;
在不存在网络延迟和及时接收的话,发送一次,就会接收一次
来灵 2011-08-26
  • 打赏
  • 举报
回复
你传输层用UDP还是TCP,套接字是阻塞还是非阻塞?
如果用TCP,那么每次接收判断下已经收到的数据是否等于数据负载长度,不能则继续接收,否则完成本次接收;如果是UDP的话,每次一次接收即可。

18,356

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 网络编程
c++c语言开发语言 技术论坛(原bbs)
社区管理员
  • 网络编程
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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