UDP直连 发送告诉数据时丢包 求解决办法...

space_006 2011-06-09 10:25:16
网络环境:两台电脑通过千兆交换机直连,千兆网卡,一台千兆交换机,千兆网线
测试一:在tcp环境下进行测试,网络速度可以达到800mbps,接收端把数据接到缓存中,再写入硬盘,数据没有丢失
(发送端开启一个发送线程,接收端开启一个接收线程)
测试二:在udp环境下进行测试,网络速度达到800mbps,接收端把数据接到缓存中,最后再写入硬盘,但是从接到的包数量来看,是小于发端发送的包数目的,写入硬盘的数据大小明显小于发端的的数据。
(发送端开启一个发送线程,接收端开启一个接收线程)

发端在应用程序中的sendto每次都调用成功,有可能是发端的数据没有传到交换机吗?或者造成这个丢包现象的原因是什么?有没有解决的办法?
谢谢!
...全文
1023 25 打赏 收藏 转发到动态 举报
写回复
用AI写文章
25 条回复
切换为时间正序
请发表友善的回复…
发表回复
wpllg 2011-07-04
  • 打赏
  • 举报
回复
如果是局域网,可以修改udp包的大小,比如32K一个包,这样可以大大提高局域网发送速度。

我用UDX测试可以轻松跑到800mbps.
wpllg 2011-06-13
  • 打赏
  • 举报
回复
对于这种大流量数据,基本达到网络极限,而且有IO操作,可能会因为延时造成网络数据被覆盖,应该用可靠UDP传输,解决你的问题,可以利用UDX协议,UDT协议完成传输。
yaozhiyong110 2011-06-13
  • 打赏
  • 举报
回复
[Quote=引用 22 楼 conry 的回复:]
只要是正确的ip地址,在windows下sendto永远是成功的,操作系统丢出去就不管了
[/Quote]

无语....
Conry 2011-06-12
  • 打赏
  • 举报
回复
只要是正确的ip地址,在windows下sendto永远是成功的,操作系统丢出去就不管了
WOAITANGPU 2011-06-12
  • 打赏
  • 举报
回复
不懂啊,不好意思,顶一下吧
space_006 2011-06-12
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 yaozhiyong110 的回复:]
返回值代表什么 自己查msdn 返回值1000不代表成功发了1000 那要这个返回值干嘛???
[/Quote]

您说的那个处理流程我的程序里面是有的,在用tcp发送时经常会遇到返回的发送字节数小于设定字节数的情况呢,在udp发送时我还没遇到过,比如设置每次发送1024(关于这个数字我也是随便设的,可以设成800,600,1200.。都可以的),返回的都是1024,如果过快的调用sendto会不会导致下层的协议栈满?大哥您对这个有了解过吗?
jsyren 2011-06-12
  • 打赏
  • 举报
回复
如果是大规模的数据传输,用tcp更好一些,更有安全保证,比如传送大的文件。
如果数据量比较小,比如QQ聊天这样的,几分钟才发送那么几个字,还是udp更好一些。因为本身数据量小,一般接受不会出现什么问题!



以上个人看法,请斧正!
yaozhiyong110 2011-06-12
  • 打赏
  • 举报
回复
[Quote=引用 15 楼 space_006 的回复:]
引用 14 楼 yaozhiyong110 的回复:
返回值代表什么 自己查msdn 返回值1000不代表成功发了1000 那要这个返回值干嘛???


您说的那个处理流程我的程序里面是有的,在用tcp发送时经常会遇到返回的发送字节数小于设定字节数的情况呢,在udp发送时我还没遇到过,比如设置每次发送1024(关于这个数字我也是随便设的,可以设成800,600,1200.。都可以的),返回……
[/Quote]

这个当然也取决于你接收的流程 接的很慢 那发送端当然一下就缓冲区满了啊

这时候发送端该“休息”了
chenjiawei007 2011-06-12
  • 打赏
  • 举报
回复
sendto语句返回结果是发送字节数, 如果长度小于缓冲长度,需要循环发送。
chenjiawei007 2011-06-12
  • 打赏
  • 举报
回复

检查你接受导数据后,是否完全的将数据放入自己的缓存,

然后再检查,自己写文件的缓存,是否存在数据丢失。

chenjiawei007 2011-06-12
  • 打赏
  • 举报
回复
看楼上猜测的太多了,模型完全是在tcp/ip上层做的,如果采用模型没问题,问题说明就很简单了,
是自己处理数据不够快,导致的丢包。

你的网络状况是很不错了,导致丢包的,不用去怀疑底层,基本就是你在recvfrom的逻辑出现问题
space_006 2011-06-11
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 yaozhiyong110 的回复:]
引用 5 楼 space_006 的回复:
引用 2 楼 yaozhiyong110 的回复:
你有判断sendto的返回值吗? 凭什么说 sendto每次都调用成功????


我判定了它的返回值的。。。每次发送1024字节的包 如果发送的包字节大小不等于1024的话 程序报错。。


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

我的意思是把每个包的大小设置为1024,那么每次成功发送的话返回值就应该是1024,如果sendto返回值为其他的话通过自己编写代码来报错..包的大小设置以后就不改变了。。也就是在我的发送端每次调用sendto返回值都是1024,这个能不能确认发送方面就没有错误了呢?之前有人提醒我说连续的调用sendto可能会导致下层的协议栈缓存满(而且我的发送速率要达到800mbps),导致发送端丢包,您对这个有什么看法呢?谢谢!
yaozhiyong110 2011-06-11
  • 打赏
  • 举报
回复
返回值代表什么 自己查msdn 返回值1000不代表成功发了1000 那要这个返回值干嘛???
yaozhiyong110 2011-06-11
  • 打赏
  • 举报
回复
如果现在有两个客户端同时给服务端发数据 怎么办?

A发送4096 结果第一次只成功了1000 这是B也发送4096 也成功了1000

这时A又发了剩下的3096 你的流程 支持吗? 会把第一次B的1000当A发的?

好好想想吧...
yaozhiyong110 2011-06-11
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 space_006 的回复:]
引用 10 楼 yaozhiyong110 的回复:
引用 5 楼 space_006 的回复:
引用 2 楼 yaozhiyong110 的回复:
你有判断sendto的返回值吗? 凭什么说 sendto每次都调用成功????


我判定了它的返回值的。。。每次发送1024字节的包 如果发送的包字节大小不等于1024的话 程序报错。。


谁规定的udp就要1024的发数据 不……
[/Quote]

一次发多少数据 取决于你的业务需求 局域网传文件 我一次发4096 8172 都可以
说白了 根据网络状态设置一个合理值就可以了 怎么会一定是1024?

假设我一次发送4096 返回值是1000 我该做什么? 把剩下的3096 再发一次

返回值又告诉我 这次又只发了1000 接着呢 该怎么做 你懂的!

你的问题不在于一次该发多少 而是你没有设计好你的流程...
zyyoung 2011-06-10
  • 打赏
  • 举报
回复
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可能会更适合你!
向立天 2011-06-10
  • 打赏
  • 举报
回复
UDP丢包不是挺正常的么
给数据包编号
如果发现丢失请求重发就是了
q1q2q3q4ln 2011-06-10
  • 打赏
  • 举报
回复
你需要自己定义消息结构
1 消息类型
2 消息长度
3 消息序列号
4 XXXX
像TCP一样,自己控制丢包的判断,和请求重发

因为UDP不保证发送和接受一定成功的
yaozhiyong110 2011-06-10
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 space_006 的回复:]
引用 2 楼 yaozhiyong110 的回复:
你有判断sendto的返回值吗? 凭什么说 sendto每次都调用成功????


我判定了它的返回值的。。。每次发送1024字节的包 如果发送的包字节大小不等于1024的话 程序报错。。
[/Quote]

谁规定的udp就要1024的发数据 不这样发就报错?
space_006 2011-06-10
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 yaozhiyong110 的回复:]
你有判断sendto的返回值吗? 凭什么说 sendto每次都调用成功????
[/Quote]

我判定了它的返回值的。。。每次发送1024字节的包 如果发送的包字节大小不等于1024的话 程序报错。。
加载更多回复(5)

18,356

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 网络编程
c++c语言开发语言 技术论坛(原bbs)
社区管理员
  • 网络编程
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧