关于UDP数据传输丢包的疑问?

Demon_Agua 2010-10-13 11:13:25
今天做了个小程序,从CAsyncSocket派生了个子类,重载了OnReceive函数
在接收数据的时候,进行了个简单的计数,并无更多操作
在发送数据的时候是使用的多媒体定时器来保证定时精度
从A计算机发送到B计算机,60000包数据,每包间隔4毫秒,每包大小1000字节
通过抓包工具确认B计算机网卡收到了所有数据,但是B计算机上的程序计数器却总是到不了6w
丢包在100~200之间不等
我发包的速率也就2mb/s,对于百兆网,速率也不是很高
查看了一下程序的CPU的占用率,偶尔能达到10%,大多数时间里都在1%左右

为啥就丢包了呢?
windows下的udp数据在多大的一个流量下能够保证不丢包呢?
请大牛们指点! ^_^
...全文
599 16 打赏 收藏 转发到动态 举报
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
FreddyHu 2010-10-19
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 jackson35296 的回复:]
对于UDP丢包问题,我做过不少研究。

广域网UDP丢包受复杂的外网环境影响,中途经过多个路由器等,随时可能丢包,广域网丢包就不多说了

主要说说局域网丢包:
1.包过大,UDP限制包最大为64K,包越大越容易丢包。楼主的1000字节是合理的
2.接包速度小于发包速度导致丢包。UDP是无连接的,当接收端接收不过来时,发送端也不会降低发送速度,当
发送的字节 - 接收字节 > 网卡缓冲……
[/Quote]
学习一下。。
Demon_Agua 2010-10-18
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 jackson35296 的回复:]

发送速度太快,超过网卡,路由器或交换器等设备的带宽导致丢包。
现在的网卡通常是100M bps网卡,理论速度是12.5MB/S。楼主说的速度是2M/S,应该在网卡的承受范围内,但是否考虑了交换机和路由器的速度?交换机和路由器通常都是 100M bps以上,如果用公司的网络测试,假如你的另外两个同事正在传大文件,占用了大量带宽,你以2M/S发送UDP数据,必然会造成一些丢包
[/Quote]
Sorry 我是2Mbps
今天尝试开大接受缓存做测试,发现把缓存开到64k、1m和32m的时候,基本6w包能保证丢不超过2包
换了几台机器测试,情况也差不多
jackson35296 2010-10-18
  • 打赏
  • 举报
回复
对于UDP丢包问题,我做过不少研究。

广域网UDP丢包受复杂的外网环境影响,中途经过多个路由器等,随时可能丢包,广域网丢包就不多说了

主要说说局域网丢包:
1.包过大,UDP限制包最大为64K,包越大越容易丢包。楼主的1000字节是合理的
2.接包速度小于发包速度导致丢包。UDP是无连接的,当接收端接收不过来时,发送端也不会降低发送速度,当
发送的字节 - 接收字节 > 网卡缓冲区 时,网卡就把多余的包丢弃。
在TCP协议中,当缓冲区接近满时,网卡会通知发送端降低发送速度,而UDP不会
通常是下面这种情况造成
发送端:
while()
{
SentTo()
...//其他的逻辑用时50ms
}
接收端
while()
{
RecvFrom()
...//处理数据的逻辑用时100ms
}

由于100ms > 50ms,如果数据量较大,发送-接收>网卡缓冲区,则丢包

对于问题2的排查,可以在发送端加sleep()进行测试,降低发送速度。如果要实现快速接收,接收的循环里不允许做费时操作,要维持一个缓冲队列,收到数据后直接扔到缓冲区,由另外一个线程从队列中取出数据再处理。总之,不要在接收线程里处理数据。

3.发送速度太快,超过网卡,路由器或交换器等设备的带宽导致丢包。
现在的网卡通常是100M bps网卡,理论速度是12.5MB/S。楼主说的速度是2M/S,应该在网卡的承受范围内,但是否考虑了交换机和路由器的速度?交换机和路由器通常都是100M bps以上,如果用公司的网络测试,假如你的另外两个同事正在传大文件,占用了大量带宽,你以2M/S发送UDP数据,必然会造成一些丢包。

对于第三个问题,应该确保交换机或路由器不受其他客户端影响

总之,要尽量确保UDP在局域网可靠传输,要做到尽量小的数据总量,尽量慢的发送速度,尽量快的接收速度和必要的数据缓冲处理,尽量小的网络影响
Demon_Agua 2010-10-17
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 cjy5318 的回复:]

查查网卡驱动跟tcpip之间还有没有中间层驱动(这里可能出问题),或者干脆换个机器试试。
[/Quote]

今天换的两台机器是通过无线路由器连接的,54M
之前是有线连接100M
今天的丢包还少不少,看来机器的差别还是有影响……
Demon_Agua 2010-10-17
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 q342210738 的回复:]

udp本生就是不可靠连接,如果全部数据都收到,那就有点不太正常了吧?
[/Quote]

今天换了两台电脑,出现了一次60000包都没丢的情况……
lyingbo 2010-10-16
  • 打赏
  • 举报
回复
udp本生就是不可靠连接,如果全部数据都收到,那就有点不太正常了吧?

relaxisland 2010-10-15
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 cjy5318 的回复:]

UDP不会粘包。
[/Quote]

原来如此,学艺不精,见笑了。
teleinfor 2010-10-14
  • 打赏
  • 举报
回复
我晕倒啊,你怎么就知道你的每个报文是对应的一个recvfrom呢?你要确认的就是你的数据内容是否完整,底层的协议数据处理你清楚么?IP分片还有可能让你UDP报文分成两个呢。。。
[Quote=引用 2 楼 demon_agua 的回复:]
引用 1 楼 teleinfor 的回复:
你如何验证的B机器网卡收到了所有发过来的UDP报文?是通过wireshark抓包看的么?

我用的Ethreal


引用 1 楼 teleinfor 的回复:
最好上来你的UDP捕获端代码看看问题。


我在OnReceive函数里面定义了一个静态局部变量,在执行了Recv之后做了个自加
我感觉已经不能再简单了……
大概如下:
……
[/Quote]
傻X 2010-10-14
  • 打赏
  • 举报
回复
UDP不丢包的方法,应用层自主协议封装,但是这样会失去效率。楼主你丢包的缘故是服务器端RECVFROM数据的时候,客户端又发数据了,因为UDP,客户端也不管,自然丢包了,另外你CPU10%的话,其实你看到的是1-2秒的平均值,就是说当中有一瞬间CPU的占用率是99%的,如果那时候数据发来,自然不处理的。你1%丢包率还算比较低的
cjy5318 2010-10-14
  • 打赏
  • 举报
回复
查查网卡驱动跟tcpip之间还有没有中间层驱动(这里可能出问题),或者干脆换个机器试试。
cjy5318 2010-10-14
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 teleinfor 的回复:]
我晕倒啊,你怎么就知道你的每个报文是对应的一个recvfrom呢?你要确认的就是你的数据内容是否完整,底层的协议数据处理你清楚么?IP分片还有可能让你UDP报文分成两个呢。。。

引用 2 楼 demon_agua 的回复:
引用 1 楼 teleinfor 的回复:
你如何验证的B机器网卡收到了所有发过来的UDP报文?是通过wireshark抓包看的么?

我用的Ethreal

……
[/Quote]

要是拆分了,那岂不是应该多了,更不可能少了……
cjy5318 2010-10-14
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 relaxisland 的回复:]
引用楼主 demon_agua 的回复:
今天做了个小程序,从CAsyncSocket派生了个子类,重载了OnReceive函数
在接收数据的时候,进行了个简单的计数,并无更多操作
在发送数据的时候是使用的多媒体定时器来保证定时精度
从A计算机发送到B计算机,60000包数据,每包间隔4毫秒,每包大小1000字节
通过抓包工具确认B计算机网卡收到了所有数据,但是B计算机上的程序计数器却总……
[/Quote]

UDP不会粘包。
Demon_Agua 2010-10-14
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 teleinfor 的回复:]
我晕倒啊,你怎么就知道你的每个报文是对应的一个recvfrom呢?你要确认的就是你的数据内容是否完整,底层的协议数据处理你清楚么?IP分片还有可能让你UDP报文分成两个呢。。。
[/Quote]
底层的协议数据处理我确实不太清楚,小于MTU的UDP报文也能被拆包我也是第一次听说……

我做过简单的TRACE,包长都是1k
数据报套接字和流套接字还是很不一样的 ^_^

relaxisland 2010-10-14
  • 打赏
  • 举报
回复
[Quote=引用楼主 demon_agua 的回复:]
今天做了个小程序,从CAsyncSocket派生了个子类,重载了OnReceive函数
在接收数据的时候,进行了个简单的计数,并无更多操作
在发送数据的时候是使用的多媒体定时器来保证定时精度
从A计算机发送到B计算机,60000包数据,每包间隔4毫秒,每包大小1000字节
通过抓包工具确认B计算机网卡收到了所有数据,但是B计算机上的程序计数器却总是到不了6w
丢包在100~200之间不等……
[/Quote]
这个。。。。
数据都收到了,那就不是丢包问题了。
至于接收的次数跟发送的次数,应该是很正常的,
udp不是很清楚,tcp协议对数据传送做了很多优化,比如为了防止小数据包发送浪费宽带,频繁发送的包会合并发送(200ms内的包)。tcp的话,可以用SetSockOpt 设置属性,TCP_NODELAY
udp是不是有没有类似的,需要查一下。



Demon_Agua 2010-10-14
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 teleinfor 的回复:]
你如何验证的B机器网卡收到了所有发过来的UDP报文?是通过wireshark抓包看的么?
[/Quote]
我用的Ethreal

[Quote=引用 1 楼 teleinfor 的回复:]
最好上来你的UDP捕获端代码看看问题。
[/Quote]

我在OnReceive函数里面定义了一个静态局部变量,在执行了Recv之后做了个自加
我感觉已经不能再简单了……
大概如下:
.......
static int nCounter = 0;
char szBuffer[2000] = {0};
int nLength = 0;
nLength = Recv(....);
if( nLength > 0)
{
nCounter++;
}
.......
teleinfor 2010-10-13
  • 打赏
  • 举报
回复
你如何验证的B机器网卡收到了所有发过来的UDP报文?是通过wireshark抓包看的么?
如果确认网卡捕获到所有的UDP发送报文,那么就可能是你的program本身的问题了,1K大小的UDP报文,如果你的网卡硬件没有故障(确认6w UDP pkt收到,可以排除故障),那么对于传输而言效率应该是非常高的了。

最好上来你的UDP捕获端代码看看问题。

18,356

社区成员

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

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