网络环境:两台电脑通过千兆交换机直连,千兆网卡,一台千兆交换机,千兆网线
    测试一:在tcp环境下进行测试,网络速度可以达到800mbps,接收端把数据接到缓存中,再写入硬盘,数据没有丢失
           (发送端开启一个发送线程,接收端开启一个接收线程)
    测试二:在udp环境下进行测试,网络速度达到800mbps,接收端把数据接到缓存中,最后再写入硬盘,但是从接到的包数量来看,是小于发端发送的包数目的,写入硬盘的数据大小明显小于发端的的数据。
           (发送端开启一个发送线程,接收端开启一个接收线程)
    
    发端在应用程序中的sendto每次都调用成功,有可能是发端的数据没有传到交换机吗?或者造成这个丢包现象的原因是什么?有没有解决的办法?
    谢谢!

解决方案 »

  1.   

    你有判断sendto的返回值吗? 凭什么说  sendto每次都调用成功????
      

  2.   

    UDP丢包了,接收端接收处理太慢?导致后续的数据包丢失?
      

  3.   


    刚才在网上搜索了相关信息 确实我的发送端是在一个循环里面连续调用sendto..可能是这方面的原因吗?
    如果既要保证800M的发送速度,又要在调用sendto一阵后进行sleep的话,可能会影响发送速度的,这个速度是硬指标呢。。那么是我的发送端要加一个拥塞控制机制?
      

  4.   

    你需要自己定义消息结构
    1 消息类型
    2 消息长度
    3 消息序列号
    4 XXXX
    像TCP一样,自己控制丢包的判断,和请求重发因为UDP不保证发送和接受一定成功的
      

  5.   

    UDP丢包不是挺正常的么
    给数据包编号
    如果发现丢失请求重发就是了
      

  6.   

    copy>>>>>>>>最近在做一个项目,在这之前,做了个验证程序. 
    发现客户端连续发来1000个1024字节的包,服务器端出现了丢包现象. 
    纠其原因,是服务端在还未完全处理掉数据,客户端已经数据发送完毕且关闭了. 有没有成熟的解决方案来解决这个问题. 
    我用过sleep(1),暂时解决这个问题,但是这不是根本解决办法,如果数据量大而多,网络情况不太好的话,还是有可能丢失.
     
    你试着用阻塞模式吧... 
    select...我开始的时候好像也遇到过..不过改为阻塞模式后就没这个问题了...
     
    采用回包机制,每个发包必须收到回包后再发下一个
     
    UDP丢包是正常现象,因为它是不安全的。
     
    丢包的原因我想并不是“服务端在还未完全处理掉数据,客户端已经数据发送完毕且关闭了”,而是服务器端的socket接收缓存满了(udp没有流量控制,因此发送速度比接收速度快,很容易出现这种情况),然后系统就会将后来收到的包丢弃。你可以尝试用setsockopt()将接收缓存(SO_RCVBUF)加大看看能不能解决问题。
     
    服务端采用多线程pthread接包处理
     
    UDP是无连接的,面向消息的数据传输协议,与TCP相比,有两个致命的缺点,一是数据包容易丢失,二是数据包无序。 
    要实现文件的可靠传输,就必须在上层对数据丢包和乱序作特殊处理,必须要有要有丢包重发机制和超时机制。 
    常见的可靠传输算法有模拟TCP协议,重发请求(ARQ)协议,它又可分为连续ARQ协议、选择重发ARQ协议、滑动窗口协议等等。 
    如果只是小规模程序,也可以自己实现丢包处理,原理基本上就是给文件分块,每个数据包的头部添加一个唯一标识序号的ID值,当接收的包头部ID不是期望中的ID号,则判定丢包,将丢包ID发回服务端,服务器端接到丢包响应则重发丢失的数据包。 
    模拟TCP协议也相对简单,3次握手的思想对丢包处理很有帮助。
     
    udp是不安全的,如果不加任何控制,不仅会丢失包,还可能收到包的顺序和发送包的顺序不一样。这个必须在自己程序中加以控制才行。 
    收到包后,要返回一个应答,如果发送端在一定时间内没有收到应答,则要重发。
    UDP本来存在丢包现象,现在的解决方案暂时考虑双方增加握手. 
    这样做起来,就是UDP协议里面加上了TCP的实现方法. 
    程序中采用的是pthread处理,丢包率时大时小,不稳定可靠
     
    我感觉原因可能有两个,一个是客户端发送过快,网络状况不好或者超过服务器接收速度,就会丢包。 
    第二个原因是服务器收到包后,还要进行一些处理,而这段时间客户端发送的包没有去收,造成丢包。 解决方法,一个是客户端降低发送速度,可以等待回包,或者加一些延迟。 
    二是,服务器部分单独开一个线程,去接收UDP数据,存放在一个缓冲区中,又另外的线程去处理收到的数据,尽量减少因为处理数据延时造成的丢包。
     
    有两种方法解决楼主的问题: 
    方法一:重新设计一下协议,增加接收确认超时重发。(推荐) 
    方法二:在接收方,将通信和处理分开,增加个应用缓冲区;如果有需要增加接收socket的系统缓冲区。(本方法不能从根本解决问题,只能改善)
     
    网络丢包,是再正常不过的了。 
    既然用UDP,就要接受丢包的现实,否则请用TCP。 
    如果必须使用UDP,而且丢包又是不能接受的,只好自己实现确认和重传,说白了,就是自己实现TCP(当然是部分和有限的简单实现)。
     
    UDP是而向无连接的,用户在实施UDP编程时,必须制定上层的协议,包括流控制,简单的超时和重传机制,如果不要求是实时数据,我想TCP可能会更适合你!
      

  7.   

    一般是接收端应用程序处理太慢,UDP数据在接受端溢出丢弃
    如果想让UDP具有一定的可靠性那就得设计重传应答机制
      

  8.   


    谁规定的udp就要1024的发数据  不这样发就报错?
      

  9.   


    我的意思是把每个包的大小设置为1024,那么每次成功发送的话返回值就应该是1024,如果sendto返回值为其他的话通过自己编写代码来报错..包的大小设置以后就不改变了。。也就是在我的发送端每次调用sendto返回值都是1024,这个能不能确认发送方面就没有错误了呢?之前有人提醒我说连续的调用sendto可能会导致下层的协议栈缓存满(而且我的发送速率要达到800mbps),导致发送端丢包,您对这个有什么看法呢?谢谢!
      

  10.   

    如果现在有两个客户端同时给服务端发数据  怎么办? A发送4096  结果第一次只成功了1000  这是B也发送4096 也成功了1000这时A又发了剩下的3096 你的流程 支持吗? 会把第一次B的1000当A发的?好好想想吧...
      

  11.   

    返回值代表什么  自己查msdn  返回值1000不代表成功发了1000  那要这个返回值干嘛???
      

  12.   


    您说的那个处理流程我的程序里面是有的,在用tcp发送时经常会遇到返回的发送字节数小于设定字节数的情况呢,在udp发送时我还没遇到过,比如设置每次发送1024(关于这个数字我也是随便设的,可以设成800,600,1200.。都可以的),返回的都是1024,如果过快的调用sendto会不会导致下层的协议栈满?大哥您对这个有了解过吗?
      

  13.   

    看楼上猜测的太多了,模型完全是在tcp/ip上层做的,如果采用模型没问题,问题说明就很简单了,
    是自己处理数据不够快,导致的丢包。你的网络状况是很不错了,导致丢包的,不用去怀疑底层,基本就是你在recvfrom的逻辑出现问题
      

  14.   

    sendto语句返回结果是发送字节数, 如果长度小于缓冲长度,需要循环发送。
      

  15.   

    如果是大规模的数据传输,用tcp更好一些,更有安全保证,比如传送大的文件。
    如果数据量比较小,比如QQ聊天这样的,几分钟才发送那么几个字,还是udp更好一些。因为本身数据量小,一般接受不会出现什么问题!以上个人看法,请斧正!
      

  16.   

    只要是正确的ip地址,在windows下sendto永远是成功的,操作系统丢出去就不管了
      

  17.   

    对于这种大流量数据,基本达到网络极限,而且有IO操作,可能会因为延时造成网络数据被覆盖,应该用可靠UDP传输,解决你的问题,可以利用UDX协议,UDT协议完成传输。
      

  18.   

    如果是局域网,可以修改udp包的大小,比如32K一个包,这样可以大大提高局域网发送速度。我用UDX测试可以轻松跑到800mbps.