为什么我的程序客户端接受数据一会儿就不行了呢? 我用socket传输视频数据,服务器端负责不断发送捕捉到的视频数据,客户端负责接受和播放数据,我是用socket api来写的,但是客户端只接受了一会儿就死掉了,不知道是怎么回事???而服务器端还是不断发送数据 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 我用socket传输视频数据,服务器端负责不断发送捕捉到的视频数据,客户端负责接受和播放数据,我是用socket api来写的,但是客户端只接受了一会儿就死掉了,不知道是怎么回事???而服务器端还是不断发送数据不发送视频数据的时候要大一些呢??接受端我是这样的:for(;;){ TotalDataRece =0; //总共已经接受到的数据 EachDataRece = 0; //每次实际接受到的数据 EachDataToRead = 0; //每次需要读取的数据 if((TotalDataRece = recv(recesock, pData, 1024, 0)) <0) { int a = GetLastError(); sprintf(szBuf, "WinSock receive error code : %d", WSAGetLastError()); AfxMessageBox(szBuf); closesocket(recesock); return -1; } memcpy(pPlayInfo, pData, 40);//接受数据的前40个字节包含了每一视频帧的信息,包括视频数据的大小 dSize = pPlayInfo->biSizeImage; //每一帧视频数据的大小 if(dSize == 0) { AfxMessageBox("receive error !"); return -1; } len = dSize + fSize; //每一帧的总共大小,视频头+视频数据 while (TotalDataRece < len) { EachDataToRead = min(1024, len-TotalDataRece);//每一帧的数据量len在4k-10k之间大小不等。if((EachDataRece = recv(recesock, pData+TotalDataRece, EachDataToRead, 0))<0) { int a = GetLastError(); sprintf(szBuf, "WinSock receive error code : %d", WSAGetLastError()); AfxMessageBox(szBuf); closesocket(recesock); return -1; } TotalDataRece += EachDataRece; } VideoPlayback(pData); //播放收到的每一个视频帧,另外一个函数, 这是程序的客户端,只能接受大概4-5秒钟,就停在哪儿了,不能正确播放,而服务器端还在发送数据,这个是怎么回事,请大侠不吝赐教 fsize在哪里定义的,是不是能肯定一定对啊?若不对,那在下一次读取pPlayInfo的时候,流数据就不对齐呢,很可能会导致你的VideoPlayback(pData); 函数出错。建议楼主检查一下len的值是否大于你pData的缓冲区最大值,可能会造成写越界,导致程序异常。 fsize 定义成了一个全局变量,而且已经赋值为40,即是视频头的40个字节pData设置为10k的缓冲区了,在程序初始化时就分配好了,该缓冲区只接受一帧数据(每一帧的大小len的值在3k-10k之间不等),调用videoplay(pData)后即回放了该帧后就把pData清空了,即清除掉接受到的数据这样pData还是指向该缓冲区的首地址。接着接受下一帧就是在for循环里面。我现在的情况是能接受到4-5秒的视频,即大概有120-150帧的视频数据并能正确显示,然后就会停止不动了。我不知道这是怎么回事 dSize = pPlayInfo->biSizeImage; //每一帧视频数据的大小 if(dSize == 0) { AfxMessageBox("receive error !"); return -1; } len = dSize + fSize; //每一帧的总共大小,视频头+视频数据len有可能大于你缓冲区的极限。加上:if(len?>maxbuffer){return -1;}wan 网络上收到的数据包不能100%的正确,所以很可能得出的SIZE是个很大的值,这样就会造成内存写越界。 每一帧的大小在3k-10k之间,fsize是个40字节的结构,包含了视频数据的信息dsize是视频数据的大小。我的缓冲区设在10k以上,我觉得不太可能是这个错误。如果不能保证数据100%正确,那么应该怎么发送呢?是不是分开发送视频头和视频数据? 你用的是tcp吧?如果是,你能确保第一个recv()收到到的数据是40字节?如果小于40字节或者是大于40字节怎么办?tcp是数据流,这样接受估计会出问题。int len = 0;int framelen = 0;int HaveRecvlen = 0;char buf[65532];ZeroMemory(buf, 65532);for(;;){ len = recv(recesock, pData, 10280, 0));//要考虑len<0的情况if ((len + HaveRecvlen) < 40){ memcpy(buf + HaveRecvlen, pData, len); HaveRecvlen += len; continue;}else{ memcpy(buf + HaveRecvlen, pData, len); HaveRecvlen += len; memcpy(pPlayInfo, buf, 40); dSize = pPlayInfo->biSizeImage; framelen = dSize + fSize; //每一帧的总共大小,视频头+视频数据 if (HaveRecvlen >= (40+framelen)) { memcpy(pData, buf+40, framelen);//取得视频头+视频数据 VideoPlayback(pData); //播放收到的每一个视频帧,另外一个函数, HaveRecvlen = HaveRecvlen - 40 - framelen; len = 0; memcpy(buf, buf+40+framelen, HaveRecvlen);//不知会不会有问题? continue; }//end if else { while(1){ len = recv(recesock, pData, 10280, 0)); memcpy(buf + HaveRecvlen, pData, len); HaveRecvlen += len; if (HaveRecvlen >= (40+framelen)) { memcpy(pData, buf+40, framelen);//取得视频头+视频数据 VideoPlayback(pData); //播放收到的每一个视频帧,另外一个函数, HaveRecvlen = HaveRecvlen - 40 - framelen; len = 0; memcpy(buf, buf+40+framelen, HaveRecvlen); break; }//end if else { continue; } }//end while }//end else}//end else}//end for 上面的代码没有经过测试也没有仔细考虑,防错也免了,不知行不行? 传送视频最好用udp,效率高,安全,丢掉一些帧可以接受。 我发送端是将每一帧的视频头40个字节+视频数据放在一个缓冲区里面,然后一起发送,接受端之所以开始接受1024个字节,这个我想把接受到的数据(应该是1024个字节,即使不是也应该大于40个字节吧)前面的40个字节拷贝出来到pplayinfo这个结构中,然后取这个结构中视频数据的大小,接着接受剩余的视频数据。 recv(recesock, pData, 1024, 0));中的1024只是表示最多收到1024字节的数据,他实际上收到多少数据是要看recv()的返回值 1。你在接收视频包头40个字节的时候,没有判断接收大小是否>=40字节就直接取其中大小长度字段,可能该值所在内存空间是一快未被初始化的空间,这里是个隐患。在INTERNET里任何时候接收数据最好接收后和你想接收的字节数进行一下比对,这才是安全的,哪怕只有40字节之少。2。如果不是因为接收数据的问题,你应该从服务器打包发送视频流和播放视频数据这2个方面来进行检查。服务器打包发送是否真的打包真确?发送是否真的全部发完了?还有食品播放是否能够正常播放视频,这些都可以影响而出现你所描述的问题。 int len = 0;int framelen = 0;int HaveRecvlen = 0;char buf[65532];ZeroMemory(buf, 65532);for(;;){ len = recv(recesock, pData, 10280, 0));//要考虑len<0的情况if ((len + HaveRecvlen) < 40){ memcpy(buf + HaveRecvlen, pData, len); HaveRecvlen += len; continue;}else{ memcpy(buf + HaveRecvlen, pData, len); HaveRecvlen += len; memcpy(pPlayInfo, buf, 40); dSize = pPlayInfo->biSizeImage; framelen = dSize; //视频数据的长度 if (HaveRecvlen >= (40+framelen)) { memcpy(pData, buf+40, framelen);//取得视频数据 VideoPlayback(pData); //播放收到的每一个视频帧,另外一个函数, HaveRecvlen = HaveRecvlen - 40 - framelen; len = 0; memcpy(buf, buf+40+framelen, HaveRecvlen);//不知会不会有问题? continue; }//end if else { while(1){ len = recv(recesock, pData, 10280, 0)); memcpy(buf + HaveRecvlen, pData, len); HaveRecvlen += len; if (HaveRecvlen >= (40+framelen)) { memcpy(pData, buf+40, framelen);//取得视频数据 VideoPlayback(pData); //播放收到的每一个视频帧,另外一个函数, HaveRecvlen = HaveRecvlen - 40 - framelen; len = 0; memcpy(buf, buf+40+framelen, HaveRecvlen); break; }//end if else { continue; } }//end while }//end else}//end else}//end for 你也没有理解我的意思,你的程序中的第一个recv():recv(recesock, pData, 1024, 0)并不能保证一定收到了40个字节,虽然你希望收到1024字节。 现在的显示器现实还需要调色板吗? SDK中如何接受到Edit控件中的消息 互换vector内数据,谢谢! VC中关于char和TCHAR之间转换的问题 CLR调用DLL的问题 求助! 在哪儿下载ODBC(for Windows95)的安装文件 怎么在软件中让用户自己设置数据库链接字符串? 请告诉我怎样在chtmlview 中保存WEB页的内容 我想深入学习DCOM、COM+,请给小弟介绍一本好书。 进程内 api hook ,奇怪的问题, 我自己写了个win32的控制台下程序,请问。。。
客户端负责接受和播放数据,我是用socket api来写的,
但是客户端只接受了一会儿就死掉了,不知道是怎么回事???
而服务器端还是不断发送数据不发送视频数据的时候要大一些呢??接受端我是这样的:
for(;;)
{ TotalDataRece =0; //总共已经接受到的数据
EachDataRece = 0; //每次实际接受到的数据
EachDataToRead = 0; //每次需要读取的数据
if((TotalDataRece = recv(recesock, pData, 1024, 0)) <0)
{
int a = GetLastError();
sprintf(szBuf, "WinSock receive error code : %d", WSAGetLastError());
AfxMessageBox(szBuf);
closesocket(recesock);
return -1;
}
memcpy(pPlayInfo, pData, 40);
//接受数据的前40个字节包含了每一视频帧的信息,包括视频数据的大小
dSize = pPlayInfo->biSizeImage; //每一帧视频数据的大小
if(dSize == 0)
{
AfxMessageBox("receive error !");
return -1;
}
len = dSize + fSize; //每一帧的总共大小,视频头+视频数据
while (TotalDataRece < len)
{
EachDataToRead = min(1024, len-TotalDataRece);
//每一帧的数据量len在4k-10k之间大小不等。
if((EachDataRece = recv(recesock, pData+TotalDataRece, EachDataToRead, 0))<0)
{
int a = GetLastError();
sprintf(szBuf, "WinSock receive error code : %d", WSAGetLastError());
AfxMessageBox(szBuf);
closesocket(recesock);
return -1;
}
TotalDataRece += EachDataRece; }
VideoPlayback(pData); //播放收到的每一个视频帧,另外一个函数,
这是程序的客户端,只能接受大概4-5秒钟,就停在哪儿了,不能正确播放,
而服务器端还在发送数据,这个是怎么回事,请大侠不吝赐教
若不对,那在下一次读取pPlayInfo的时候,流数据就不对齐呢,很可能会导致你的VideoPlayback(pData); 函数出错。
建议楼主检查一下len的值是否大于你pData的缓冲区最大值,可能会造成写越界,导致程序异常。
pData设置为10k的缓冲区了,在程序初始化时就分配好了,该缓冲区只接受一帧数据(每一帧的大小len的值在3k-10k之间不等),调用videoplay(pData)后即回放了该帧后就把pData清空了,即清除掉接受到的数据
这样pData还是指向该缓冲区的首地址。接着接受下一帧就是在for循环里面。我现在的情况是能接受到4-5秒的视频,即大概有120-150帧的视频数据并能正确显示,
然后就会停止不动了。我不知道这是怎么回事
if(dSize == 0)
{
AfxMessageBox("receive error !");
return -1;
}
len = dSize + fSize; //每一帧的总共大小,视频头+视频数据
len有可能大于你缓冲区的极限。
加上:
if(len?>maxbuffer)
{
return -1;
}
wan
dsize是视频数据的大小。我的缓冲区设在10k以上,我觉得不太可能是这个错误。如果不能保证数据100%正确,那么应该怎么发送呢?是不是分开发送视频头和视频数据?
int framelen = 0;
int HaveRecvlen = 0;
char buf[65532];ZeroMemory(buf, 65532);
for(;;)
{
len = recv(recesock, pData, 10280, 0));
//要考虑len<0的情况
if ((len + HaveRecvlen) < 40)
{
memcpy(buf + HaveRecvlen, pData, len);
HaveRecvlen += len;
continue;
}
else
{
memcpy(buf + HaveRecvlen, pData, len);
HaveRecvlen += len;
memcpy(pPlayInfo, buf, 40);
dSize = pPlayInfo->biSizeImage;
framelen = dSize + fSize; //每一帧的总共大小,视频头+视频数据 if (HaveRecvlen >= (40+framelen))
{
memcpy(pData, buf+40, framelen);//取得视频头+视频数据
VideoPlayback(pData); //播放收到的每一个视频帧,另外一个函数, HaveRecvlen = HaveRecvlen - 40 - framelen;
len = 0;
memcpy(buf, buf+40+framelen, HaveRecvlen);//不知会不会有问题?
continue;
}//end if
else
{
while(1){
len = recv(recesock, pData, 10280, 0));
memcpy(buf + HaveRecvlen, pData, len);
HaveRecvlen += len;
if (HaveRecvlen >= (40+framelen))
{
memcpy(pData, buf+40, framelen);//取得视频头+视频数据
VideoPlayback(pData); //播放收到的每一个视频帧,另外一个函数, HaveRecvlen = HaveRecvlen - 40 - framelen;
len = 0;
memcpy(buf, buf+40+framelen, HaveRecvlen);
break;
}//end if
else
{
continue;
}
}//end while
}//end else
}//end else
}//end for 上面的代码没有经过测试也没有仔细考虑,防错也免了,不知行不行?
接受端之所以开始接受1024个字节,这个我想把接受到的数据(应该是1024个字节,即使不是也应该大于40个字节吧)前面的40个字节拷贝出来到pplayinfo这个结构中,然后取这个结构中视频数据的大小,接着接受剩余的视频数据。
2。如果不是因为接收数据的问题,你应该从服务器打包发送视频流和播放视频数据这2个方面来进行检查。服务器打包发送是否真的打包真确?发送是否真的全部发完了?还有食品播放是否能够正常播放视频,这些都可以影响而出现你所描述的问题。
int framelen = 0;
int HaveRecvlen = 0;
char buf[65532];ZeroMemory(buf, 65532);
for(;;)
{
len = recv(recesock, pData, 10280, 0));
//要考虑len<0的情况
if ((len + HaveRecvlen) < 40)
{
memcpy(buf + HaveRecvlen, pData, len);
HaveRecvlen += len;
continue;
}
else
{
memcpy(buf + HaveRecvlen, pData, len);
HaveRecvlen += len;
memcpy(pPlayInfo, buf, 40);
dSize = pPlayInfo->biSizeImage;
framelen = dSize; //视频数据的长度 if (HaveRecvlen >= (40+framelen))
{
memcpy(pData, buf+40, framelen);//取得视频数据
VideoPlayback(pData); //播放收到的每一个视频帧,另外一个函数, HaveRecvlen = HaveRecvlen - 40 - framelen;
len = 0;
memcpy(buf, buf+40+framelen, HaveRecvlen);//不知会不会有问题?
continue;
}//end if
else
{
while(1){
len = recv(recesock, pData, 10280, 0));
memcpy(buf + HaveRecvlen, pData, len);
HaveRecvlen += len;
if (HaveRecvlen >= (40+framelen))
{
memcpy(pData, buf+40, framelen);//取得视频数据
VideoPlayback(pData); //播放收到的每一个视频帧,另外一个函数, HaveRecvlen = HaveRecvlen - 40 - framelen;
len = 0;
memcpy(buf, buf+40+framelen, HaveRecvlen);
break;
}//end if
else
{
continue;
}
}//end while
}//end else
}//end else
}//end for