tempad
Readygo技术搜索引擎 >>游戏开发 >> 关于用UDP广播大数据的问题:发送端显示全部发送出去了,接收端却只能收到部分数据.

关于用UDP广播大数据的问题:发送端显示全部发送出去了,接收端却只能收到部分数据.

Readygo技术搜索引擎 网络搜索 efish 2008-1-17 1:59:43

关于用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

责任编辑: efish 参与评论 查找更多:
相关文章
有一个表左右很长,如何才能使它页显示 有一个表左右很长,如何才能使它页显示
machine.config文件配置问题——就这点分拉,全部风尚 machine.config文件配置问题——就这点分拉,全部风尚
伽马校正的资料 伽马校正的资料
放掉最后30分,我的共享连接为什么不行?? 放掉最后30分,我的共享连接为什么不行??
ie不能显示网页背景!怎么办? ie不能显示网页背景!怎么办?
asp问题?!那位大侠帮下忙,有什么错误,给看看 asp问题?!那位大侠帮下忙,有什么错误,给看看
关于把excel的数据逐条读入到数据库中问题 关于把excel的数据逐条读入到数据库中问题
新装了VFP7。0,不过初看界面似乎有点失望,记得以前… 新装了VFP7。0,不过初看界面似乎有点失望,记得以前(小魏2002 xiaowei_2002)
在jbuilder里运行程序时,总是弹出一个界面(run),那是… 在jbuilder里运行程序时,总是弹出一个界面(run),那是怎么回事?请教!!
有没有了解东软电子商务部的啊 有没有了解东软电子商务部的啊
2秒记住本站域名

玩过泡泡龙吗?Readygo?Go! 再加上.Com.Cn的后缀,那就是大名小顶的readygo.com.cn

分类导航
Readygo技术搜索引擎