recv函数接收数据

RLib 2010-08-22 04:08:24

没办法,因为数据是未知大小的,使用recv函数接收数据时,可能收不完整,总不可能设置一个超大缓冲区吧?
所以,按照自己的想法改造了下,问题解决了,但又感觉无论是代码还是效率都很鸡肋,怎么办?
大大们帮忙看看吧。。。。。。。。。。。





//分块接收不定长数据
int BlockSize = 1,BufferSize = BlockSize; //块大小,初始缓冲区大小
int thisRecv = 0,allRecv = 0; //本次接收长度,总已接收长度
LPSTR Buffer = new CHAR[BlockSize]; //接收缓冲区
LPSTR Buffer_TempCpy=Buffer; //接收缓冲区的指针临时副本
while(true)
{
thisRecv=recv(s,Buffer+allRecv,BlockSize,0);
//相应处理
if(thisRecv<=0) //接收0长度或者出错
{
if(thisRecv==SOCKET_ERROR) //异常
{
Err();
delete[] Buffer;
return NULL;
}
//接收完成,哈
break;
}
else if (thisRecv<BlockSize) //一次没有接收完指定分块大小
{
BlockSize-=thisRecv;//为了继续接收剩余,藐视没有用?
}
allRecv+=thisRecv; //更新已接收长度
if (allRecv==BufferSize) //缓冲区存满了
{
//开辟更多空间,貌似会产生内存碎片?
Buffer=new CHAR[allRecv+BlockSize];
memcpy_s(Buffer,allRecv,Buffer_TempCpy,allRecv); //复制已接收数据
delete[] Buffer_TempCpy; //删除旧数据
BufferSize+=BlockSize; //更新缓冲区大小
Buffer_TempCpy=Buffer;
}
}
...全文
1504 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
RLib 2010-12-07
  • 打赏
  • 举报
回复
有人???????
RLib 2010-08-23
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 djj315 的回复:]
楼主,你也可以把接收到的数据放到一个自定义的队列里去啊。。。
[/Quote]
[Quote=引用 7 楼 visualeleven 的回复:]
先得到数据包的大小,然后循环接收,类似下面这样
[/Quote]
要是知道数据的大小,我就没必要这么麻烦了。。。。。。。。。。。。。

现在是不知道数据大小,有可能几K,甚至几M,如果设置接收缓冲区过大,浪费。反之,不完整。
Eleven 2010-08-23
  • 打赏
  • 举报
回复
先得到数据包的大小,然后循环接收,类似下面这样
int nTotal = 255; // 比如总大小为255字节
char* buf = new char[255 + 1]; // 多分配一个
memset(buf, 0, 255+1);
int Left = 255;
int nRet = 0;
int nCount = 0;
while(Left > 0)
{
nRet = recv(s, buf+nCount, Left, 0);
if(SOCKET_ERROR == nRet)
{
// Error handler...
}
else
{
Left -= nRet;
nCount += nRet;
}
}
// 使用buf
....

// 最后delete buf
delete[] buf;
buf = NULL;
Simao 2010-08-23
  • 打赏
  • 举报
回复
楼主,你也可以把接收到的数据放到一个自定义的队列里去啊。。。
duke56 2010-08-22
  • 打赏
  • 举报
回复
另一端是不是你自己写的?

要是的话可以先发个之后的数据包的数据长度,这样接收端可以通过接收到的后边要接收的大小而New多大的缓冲区

只是纯思想...
RLib 2010-08-22
  • 打赏
  • 举报
回复
恩,其实我自己也发现了一个问题(接收的数据少于块大小时的处理)。呵呵。怕浪费把块设置小一点就行。
nick.name 2010-08-22
  • 打赏
  • 举报
回复
If the datagram or message is larger than the buffer specified, the buffer is filled with the first part of the datagram, and recv generates the error WSAEMSGSIZE. For unreliable protocols (for example, UDP) the excess data is lost; for reliable protocols, the data is retained by the service provider until it is successfully read by calling recv with a large enough buffer.

翻译下吧..

如果收到的数据大于给定的缓冲区的话,会先将一部分数据先填充到缓冲区中(我猜大小应该是缓冲区的大小),recv发引发WSAEMSGSIZE的错误(用WSAGetLastError可以获取到)。对于不可靠的协议(如UDP)来说,剩下的数据会被丢弃;对于可靠的协议(TCP是其中之一),剩下的数据将会保留,直到通过recv使用足够大的缓冲区来成功读取。


至于不准确,是因为数据的大小刚刚好为BufferSize,你再加大缓冲区就是浪费了。
RLib 2010-08-22
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 hellbelial 的回复:]
if(allRecv == BufferSize)这个判断也不够准确呀
[/Quote]
我知道UDP那样会丢包。现在是TCP。
为什么不准确呢?看不明E文的意思。。。
nick.name 2010-08-22
  • 打赏
  • 举报
回复
看代码中使用的协议是什么了,如果是TCP还好,如果是UDP的话,缓冲区不够大的话,recv会先将一部分数据放入缓冲区中,剩下的就被丢弃了,你下次再recv也取不回来...

if(allRecv == BufferSize)这个判断也不够准确呀,还是认真看下msdn吧。


If the datagram or message is larger than the buffer specified, the buffer is filled with the first part of the datagram, and recv generates the error WSAEMSGSIZE. For unreliable protocols (for example, UDP) the excess data is lost; for reliable protocols, the data is retained by the service provider until it is successfully read by calling recv with a large enough buffer.

64,662

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

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