C# 在用同步方式接受服务器数据的时候,消息数量过多,偶尔会出现200MS的延时,求大神!!

C# 在用同步方式接受服务器数据的时候,消息数量过多,偶尔会出现200MS的延时,求大神!!,第1张

遇到过类似问题——发送方的速度非常快,而接受方不仅要接收还要处理数据,相对来说就是“发快收慢”,如果接收方速度太慢就会导致延迟出现,为了不失真则应该让接收方快于发送方(香农定理)

实际上.net提供的Socket速度已经很好了,这里的ClientSocket.Receive方法几乎是立即返回数据,导致波动的主要原因还是你的打印方法

Debug.Log("数据时间:"+(DateTime.Now.Ticks-time)/10000)

我处理的方法是将Socket当作一个适配器前端看待,它只负责接收数据,并将数据送入“适配器”执行后续操作,而这个Socket前端则立即返回准备接收后续数据——对数据的具体处理则交给适配器及其执行者解决。为此创建两个线程A、B和一个公共消息队列SQ

A:用于接收数据,接收到的数据立即存放到消息队列,然后A回去准备接收一次数据

B:用于处理数据,他周期性的检查消息队列中是否有消息,如果有则一次提取若干个消息进行处理(主要是减少AB之间对于SQ的互斥检测)

这样就可以大幅度提高数据接收的效率了。

对于你的Debug.Log而言,可以选择批量输出,这这样也可以减少IO次数(IO是慢速动作),从而提高整体的运转效率

[TOC]

TCP协议中的Nagle算法

TCP中的Nagle算法

Linux下TCP延迟确认(Delayed Ack)机制导致的时延问题分析

TCP-IP详解:Delay ACK

Nagle算法为了避免网络中存在太多的小数据包,尽可能发送大的数据包。定义为在任意时刻,最多只有一个未被确认的小段。小段为小于MSS尺寸的数据块,未被确认是指数据发出去后未收到对端的ack。

Nagle算法是在网速较慢的时代的产物,目前的网络环境已经不太需要该机制,该算法在linux系统中默认关闭。

1)如果包长度达到MSS,则允许发送;

2)如果该包含有FIN,则允许发送;

3)设置了TCP_NODELAY选项,则允许发送;

4)未设置TCP_CORK选项时,若所有发出去的包均被确认,或所有发出去的小数据包(包长度小于MSS)均被确认,则允许发送。

对于规则4),就是说要求一个TCP连接上最多只能有一个未被确认的小数据包,在该分组的确认到达之前,不能发送其他的小数据包。如果某个小分组的确认被延迟了(案例中的40ms),那么后续小分组的发送就会相应的延迟。也就是说延迟确认影响的并不是被延迟确认的那个数据包,而是后续的应答包。

tcp默认使用nagle算法,最大限度的进行缓存。

优点 :避免网络中充斥着许多小数据块,降低网络负载,减少网络拥塞,提高网络吞吐

缺点 :客户端的延迟会增加,实时性降低,不适合延时要求尽量小的场景;且对于大文件传输这种场景,会降低传输速度。

用TCP_NODELAY选项可以禁止Negale 算法。此时,应用程序向内核递交的每个数据包都会立即发送出去。需要注意的是,虽然禁止了Negale 算法,但网络的传输仍然受到TCP确认延迟机制的影响。

TCP在接收到对端的报文后,并不会立即发送ack,而是等待一段时间发送ack,以便将ack和要发送的数据一块发送。当然ack不能无限延长,否则对端会认为包超时而造成报文重传。linux采用动态调节算法来确定延时的时间。

TCP在何时发送ACK的时候有如下规定:

优点 :减少了数据段的个数,提高了发送效率

缺点 :过多的delay会拉长RTT(往返时延)

可以通过TCP_QUICKACK这个选项来启动快速ACK:

所谓的CORK就是塞子的意思,形象地理解就是用CORK将连接塞住,使得数据先不发出去,等到拔去塞子后再发出去。Cork算法与Nagle算法类似,也有人把Cork算法称呼为super-Nagle。Nagle算法提出的背景是网络因为大量小包小包而导致利用率低下产生网络拥塞,网络发生拥塞的时候性能还会进一步下降,因此Nagle算法通过ACK确认包来触发新数据包的发送(ACK确认包意味着对端已经接收到了一个数据包,即有一个数据包已经离开中间网络,此时可以在向中间网络注入一个数据包块,这称呼为self-clocking)。Cork算法则更为激进,一旦打开Cork算法,TCP不关注是否有收到ACK报文,只要当前缓存中累积的数据量不足以组成一个full-sized数据包就不会将数据包发出,直到一个RTO超时后才会把不满足一个full-sized的数据包发出去(实际上是通过一个persist timer来设置的这个RTO定时时间,persist timer超时的时候就会强制发送)。

linux中可以通过TCP_CORK选项来设置socket打开Cork算法。TCP_NODELAY选项和TCP_CORK选项在linux早期版本是互斥的,但目前最新的linux版本已经可以同时打开这两个选项了,但是TCP_CORK选项的优先级要比TCP_NODELAY选项的优先级要高。

Nagle算法和CORK算法非常类似,但是它们的着眼点不一样,Nagle算法主要避免网络因为太多的小包(协议头的比例非常之大)而拥塞,而CORK算法则是为了提高网络的利用率,使得总体上协议头占用的比例尽可能的小.如此看来这二者在避免发送小包上是一致的,在用户控制的层面上,Nagle算法完全不受用户socket的控制,你只能简单的设置TCP_NODELAY而禁用它,CORK算法同样也是通过设置或者清除TCP_CORK使能或者禁用之,然而Nagle算法关心的是网络拥塞问题,只要所有的ACK回来则发包,而CORK算法却只关心内容,在前后数据包发送间隔很短的前提下(很重要,否则内核会帮你将分散的包发出),即使你是分散发送多个小数据包,你也可以通过使能CORK算法将这些内容拼接在一个包内,如果此时用Nagle算法的话,则可能做不到这一点.

优点 :提高网络的利用率

缺点 :对实时性有影响

使用TCP_CORK参数进行配置


欢迎分享,转载请注明来源:夏雨云

原文地址:https://www.xiayuyun.com/zonghe/698437.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-08-03
下一篇2023-08-03

发表评论

登录后才能评论

评论列表(0条)

    保存