目标:我有一个Socket server,需要从一个socket client接收数据,client的数据包结构是一个固定长度的包头,记录该包数据体个数及单个数据体长度,在后面跟着发送指定个数的数据体。client端的数据包(包头+N*包体)是用一个send ()发送的。服务端就是接收该包并处理。实现:在服务端接收时,我是先用一个receive()接收包头,然后取出单个包体长度和数据包个数。然后循环取数据包体,每次只取一个包体,处理。问题:如果数据包体个数不多(3--5),这样实现没问题,但是如果多了,比如8个(也不算很多啊!),服务端就接收不全数据。通常是到第3个数据包体,对方socket连接就断掉了。不知道是什么原因。好像不是时间的问题,因为这个响应时间<1秒。而我断点跟踪receive()时,超过10秒,第2,3个包体还是能够接收,但是后来的就接收不到了。我想到的解决办法是,可以先计算出所有包体一共需要缓冲区,然后动态分配一下内存,然后一次全部接收。这应该可以解决问题。但是我不明白为什么分多次接收数据包不行?经验告诉我, 多个send()发送一个数据,用一个receive()可能收不全。但是一个send(),用多个receive()应该可以收到啊?请高人指点。
目标:我有一个Socket server,需要从一个socket client接收数据,client的数据包结构是一个固定长度的包头,记录该包数据体个数及单个数据体长度,在后面跟着发送指定个数的数据体。client端的数据包(包头+N*包体)是用一个send ()发送的。服务端就是接收该包并处理。实现:在服务端接收时,我是先用一个receive()接收包头,然后取出单个包体长度和数据包个数。然后循环取数据包体,每次只取一个包体,处理。问题:如果数据包体个数不多(3--5),这样实现没问题,但是如果多了,比如8个(也不算很多啊!),服务端就接收不全数据。通常是到第3个数据包体,对方socket连接就断掉了。不知道是什么原因。好像不是时间的问题,因为这个响应时间<1秒。而我断点跟踪receive()时,超过10秒,第2,3个包体还是能够接收,但是后来的就接收不到了。我想到的解决办法是,可以先计算出所有包体一共需要缓冲区,然后动态分配一下内存,然后一次全部接收。这应该可以解决问题。但是我不明白为什么分多次接收数据包不行?经验告诉我, 多个send()发送一个数据,用一个receive()可能收不全。但是一个send(),用多个receive()应该可以收到啊?请高人指点。
你的socket是阻塞还是非阻塞?socket断开报的什么错?
to alanwang_(alan) :
阻塞的。to jennyvenus(JennyVenus) :
发送是一次发送,接收分多次to liguangyi() :
你指的是socket本身的缓冲区?怎么配置啊?如果指的我程序中的缓冲区,我的程序每次只接收指定大小的数据包,不会同时收到2个。
重新跟踪一下,socket并没有断开,而是接收的数据<指定的数据包大小!这是怎么产生的呢?网络问题应该关系不大,100M局域网。
http://expert.csdn.net/Expert/topic/1030/1030019.xml?temp=.4715845
如果你接受的数据小于指定数据包的大小,就再接收一次,接收的大小是这个包剩余数据的大小,然后把两次接收的合并就可以了。如果还不够,重复。
如果send是阻赛的,并且成功返回,发送端就应该没有问题,缓冲区也足够大了。
跟接收的时间没有关系。我猜想你有可能是把接收下来的数据丢弃了
CSocket sockTemp;
... for(int j=0;j<iRecordCount;j++)
{
ZeroMemory(&pkBody,sizeof(pkBody));
ret = sockTemp.Receive(&pkBody,sizeof(pkBody),0);
if(ret<sizeof(pkBody))
throw CMyException(...);
do others...;
}
int iBufferLen=iRecordCount*sizeof(pkBody);
ret = sockTemp.Receive(bBuffer,iBufferLen,0);数据就收全了!
即使设置成阻塞,ret = sockTemp.Receive(bBuffer,iBufferLen,0);也有可能无法收到全部数据!
必须要考虑0 < ret < iBufferLen的情况:继续接收iBufferLen - ret字节,然后合并。
SYSTEMTIME timeBegin,timeEnd;
MessageBox("开始测试");
tBegin=CTime::GetCurrentTime();
GetSystemTime(&timeBegin);
Sleep(2000);
tEnd=CTime::GetCurrentTime();
GetSystemTime(&timeEnd);
CTimeSpan span=(tEnd-tBegin);
CString tmp;
tmp.Format("%d;%d;%ld,%ld,%ld",span.GetTotalSeconds(),tEnd.GetTime()-tBegin.GetTime(),tBegin.GetTime(),tEnd.GetTime(),timeEnd.wMilliseconds-timeBegin.wMilliseconds);2种方法好像都不对!
GetTickCount()可以得到从系统启动开始,到现在经过的ms数,可用来计时