发送的包比MTU大,UDP包在接收端容易丢包,可查看接收端的网卡统计。可考虑把包切分到MTU一下再发送。
发包速度太快的话,可能有两个问题:1.接收端来不及接收导致接收端丢包。2.发送端网卡处理不过来。这个时候sendto没有返回错误,但是用netstat查看会发现SndbufErrors不断上升,有可能是网卡的输出队列太小导致。可以考虑使用ifconfig命令把txqueuelen设置大一些。
同一个端口发送的数据量太大时会导致网卡丢包,这个时候可以用netstat查看会发现SndbufErrors不断上升。sendto会返回-1.这个时候可以考虑增大/proc/sys/net/core/wmem_max的值。
这种情况尤其是同时给多个客户端发送音视频数据时导致。笔者曾经遇到过这么一次情况。一个端口向8个客户端发送视频流时,网卡流量大概400M/s,sendto会返回-1,errno 11.程序里也调用setsockopt设置了发送缓冲区为60M,然而还是会丢包。后来将系统参数/proc/sys/net/core/wmem_max设到60M才解决问题。
接收缓冲区小于发送客户端的包的大小,或者接收客户端recvfrom速度太慢,导致接收缓冲区满丢弃数据。前一种问题,可以考虑增大接收缓冲区。后一种问题,可以考虑将接收 *** 作和业务处理 *** 作分离到不同的线程来处理。
看你需要是否严谨。udp传输本来就会丢失包的现象,但是效率高。如果需求比较严谨的话 用tcp传输。不过效率就没有udp高。udp本来就是这样设计的,是本身的特性,除非你自己写个udp。包多的时候,要能保证接收端在收到数据后能立刻再次回到监听状态,以防在处理这个包的消息的时候有新的包发过来却因为接收端还未回到监听状态而造成丢包。研究一下委托回调吧。另一个是要注意每个包不要携带过长的数据量,可以拆分成若干小包后在每个包头前编号,接收端在收到后排序整理,发现哪个编号丢了返还给发送端要求冲发该吧。研究下消息队列吧。有没有问过接收端那边的设置呢。从理论上来说,UDP数据的总长度为 65535(IP最大长度)-20(IP头)-8(UDP头) = 65507个字节,但大多数系统都达不到这个长度。这一般是受到两个方面的因素限制:1) 应用程序编程接口限制。一般socket的缓冲区大小是8K,但都提供API来设置缓冲区的大小(SetSockOpt)。一般发送UDP最好不要超过512字节,这样基本可以保证不丢包(因为大部分网络和主机的MTU都大于512).
2) TCP/IP内核的限制。可能存在一些实现特性使得IP长度不能达到65535。
由于IP能够发送或接收特定长度的数据报并不意味着接收应用程序可以读取该长度的数据。因此,UDP编程接口允许应用程序指定每次返回的最大字节数。如果接收到的数据报长度大于应用程序所能处理的长度,那么会发生什么情况呢?典型的Berkeley版socket API对数据报进行截断,并丢弃任何多余的数据;SVR4下的socket API(包括Solaris 2.x) 并不截断数据报。超出部分数据在后面的读取中返回。它也不通知应用程序从单个UDP数据报中多次进行读取 *** 作;TLI API不丢弃数据。相反,它返回一个标志表明可以获得更多的数据,而应用程序后面的读 *** 作将返回数据报的其余部分。
UDP不会分片,分片是IP层做的事,而且分片重组也是IP层负责的。
如果用UDP发送数据,数据量最好不要太大,应该避免IP层和链路层分包,防止分片丢失,导致整个UDP数据包丢失
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)