关于用UDP广播大数据的问题:发送端显示全部发送出去了,接收端却只能收到部分数据.
关于用UDP广播大数据的问题:发送端显示全部发送出去了,接收端却只能收到部分数据.
楼主zoutaiqi(David)2002-11-22 20:24:00 在 VC/MFC / 网络编程 提问 关于用UDP广播大数据的问题:发送端显示全部发送出去了,接收端却只能收到部分数据.
注:如果发送端与接收端在同一台机器上,则没有任何问题,不在同一机器上,则接收断只能接收部分数据.而且接受小数据如:10K左右是没问题的.
//UDP广播时,UDP包格式
struct UDPPACKAGE
{
long i_order;//包序号
int size;//包中数据的长度
char BMPdata;//位图数据
BOOL endFlag;//用与检验是否是最后一个包
};
发送端循环部分:
while(1)
{
//按定义的包格式填充包
ZeroMemory(&buf, sizeof(UDPPACKAGE));
buf.endFlag = FALSE;//表示是否是最后一个包
buf.i_order = i++;//包索引.
//如果是最后一个包,则设置buf.endFlag = TRUE.否则设置 buf.endFlag = FALSE;
//如果是最后一个包,且包长刚好等于250时按此发送.
if ((pParam.datalength - idx) == 250)//pParam个结构,含要传输的数据及其总长度.
{
buf.endFlag = TRUE;
buf.size = 250;
memcpy(buf.BMPdata, pParam.chFileData + idx, 250);//位图数据.
ret = sendto(sendSocket, (const char *)&buf, sizeof(UDPPACKAGE), 0, (SOCKADDR *)&recv, sizeof(recv));
if (ret == SOCKET_ERROR)
{
AfxMessageBox("sendto() failed: %d", WSAGetLastError());
break;
}
break;
}
//如果是最后一个包,且包长小于250是按此发送.
if ((pParam.datalength - idx) < 250)
{
buf.size = pParam.datalength - idx;
buf.endFlag = TRUE;
memcpy(buf.BMPdata, pParam.chFileData + idx, buf.size);//位图数据.
sendto(sendSocket, (const char *)&buf, sizeof(UDPPACKAGE), 0, (SOCKADDR *)&recv, sizeof(recv));
if (ret == SOCKET_ERROR)
{
AfxMessageBox("sendto() failed: %d", WSAGetLastError());
break;
}
break;
}
//如果不是最后一个包,则按此发送.
else
{
buf.endFlag = FALSE;
buf.size = 250;
memcpy(buf.BMPdata, pParam.chFileData + idx, 250);//位图数据.
ret = sendto(sendSocket, (const char *)&buf, sizeof(UDPPACKAGE), 0, (SOCKADDR *)&recv, sizeof(recv));
if (ret == SOCKET_ERROR)
{
AfxMessageBox("sendto() failed: %d", WSAGetLastError());
break;
}
}
idx += 250;
}
在调试时所有数据都发送完了.
接收端:
char *bmpDataBuf = new char;//保存数据
long bmpdatasize = 0;
ZeroMemory(bmpDataBuf, BMPFILEMAXSIZE);
UDPPACKAGE buf;//接收UDP包的缓冲区.
int SendaddrSize = sizeof(sendaddr);
while(1)
{
ZeroMemory(&buf, sizeof(UDPPACKAGE));
ret = recvfrom(UdpRecvSock, (char *)&buf, sizeof(UDPPACKAGE), 0, (struct sockaddr *)&sendaddr, &SendaddrSize);
if (ret == SOCKET_ERROR )
{
int error = WSAGetLastError();
AfxMessageBox("UDP recvfrom() Error!");
closesocket(UdpRecvSock);
WSACleanup();
return 0;
}
curaddr = buf.i_order * 250;
//把接收到的数据存到相应的内存中
if (buf.endFlag)//表示是末尾的包.
{
memcpy(bmpDataBuf + curaddr, buf.BMPdata, buf.size);
packetEndNo = buf.i_order + 1;
bmpdatasize += buf.size;
}
else
{
memcpy(bmpDataBuf + curaddr, buf.BMPdata, buf.size);
bmpdatasize += buf.size;
}
packetNum++;
//如果包都收到了则退出循环.
if (packetNum == packetEndNo)
{
break;
}
}
接受循环中有一个很大错误:即如果最后一个包丢失了,则死循环,目前我不知道怎么解决,如何知道发送方的数据已经发送完了呢?大家有什么好的方法?
但现在主要问题在这里:当两端在同一机器上是没问题,否则只能接收到部分数据. 问题点数:100、回复次数:13Top
1 楼yuilan(于连)回复于 2002-11-23 08:18:21 得分 20
udp肯定要丢包,我有个同学,最近在做网络图像传输,才开始也是丢包严重,然后封装了同步的网络类后,好了,好像是把。我看你的代码好像用的是api,应该不会丢包太严重吧,不用mfc应该问题不大。
接受循环,可以对当前接受的包来个超时监测,如果超时,那你的那一帧就丢了吧。我个人认为你的代码有问题,也许你的网络类用的有问题。Top
2 楼yuilan(于连)回复于 2002-11-23 08:20:25 得分 0
广播,我对它不喜欢,希望你自己做个多播类。如果你很忙的话,可以向我索要代码,给我留言可以了。Top
3 楼bafadia()回复于 2002-11-23 14:49:38 得分 10
分包发送,不要一次就把所有的发送出去,可以借鉴TCP/IP协议的滑动发送方式,一次发2k,分多次发送出去Top
4 楼top_hipster(无为而无所不为)回复于 2002-11-23 15:03:16 得分 0
UDP的丢包的确容易发生,你不妨改用TCP,或者在自己的程序中使用数据监测,对没有收到的数据重发Top
5 楼top_hipster(无为而无所不为)回复于 2002-11-23 15:04:47 得分 0
UDP还有一个有趣的现象,它提交给系统的最初的一两个数据报,经常会发不出去Top
6 楼HeShe(呵呵)回复于 2002-11-23 18:05:31 得分 30
每次发送完加个sleep试试Top
7 楼zoutaiqi(David)回复于 2002-11-24 00:59:56 得分 0
to bafadia():我就是分包发送的啊!
to top_hipster(top_hipster):这是广播方式,不能用TCPTop
8 楼zoutaiqi(David)回复于 2002-11-24 01:11:10 得分 0
非常感谢yuilan(于连),其实我要做的就是用组播传输图象,我现在只是先用广播测试一下.我也知道代码有问题,希望大家给点建议,应如何做.或者大家讨论一下.例如:如何要求重发包,如何检验收到包的正确性,如何知道发送方的数据已经发送完了等.Top
9 楼zoutaiqi(David)回复于 2002-11-24 01:15:45 得分 0
TO:yuilan(于连):我的代码的确有问题,但你觉得我的代码的主要问题是在哪里呢?
希望给我点建议,谢谢!1Top
10 楼week(没有名字的树)回复于 2002-11-24 01:43:10 得分 30
在UDP方式下,要求完全可靠可能是不现实的(否则就用TCP了),
只能在容忍一定的错误情况下加以控制。
要保证一定程度的可靠,就需要通过时间戳和序列号做反馈控制
建议参考RTP协议
另外,在组播下还有一个问题,每一个接收线程(主机)的丢包情况
是独立的,如果全部由发送者重发修复是过于浪费的,虽然有一些补救方式,
但是总归比较麻烦Top
11 楼af_inet()回复于 2002-11-25 11:25:22 得分 10
week说的有道理,可以参考RTP的实现,不过我觉得在处理检验是否丢保时还是可以看看UNIX中TCP的实现,然后更具自己的需要,写成一个UDP的类!Top
12 楼yanhuahui(眼发黑)回复于 2002-11-26 15:09:24 得分 0
Tcp
Top
13 楼zoutaiqi(David)回复于 2002-12-09 13:21:44 得分 0
谢谢各位,结果我以知道,是缓冲区溢出了.Top
-
相关文章
2秒记住本站域名
玩过泡泡龙吗?Readygo?Go! 再加上.Com.Cn的后缀,那就是大名小顶的readygo.com.cn
