-
Notifications
You must be signed in to change notification settings - Fork 2.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
模拟高丢包率环境下时出现的问题 #4
Comments
你真细致呀,网络数据堆积是比较重要的一个问题。ARQ协议的信道理论可用带宽为: |
50%+75%的丢包率实在是太高了,信道几乎不可用了。因为高丢包,RTO会变的很大,这些行为和TCP也都是一致的,tcp在35%丢包时就断线了,没法工作了。其实处理“当前网络无法发送更多数据”这种事情,是上层传输逻辑的一个很重要的逻辑,不管下面是tcp还是kcp,再我们用kcp传送语音和视频,都会碰到网络震荡,这时候,语音或者视频一旦发现ikcp_waitsnd 的数据超过一个阀值就开始跳帧,不再传送新数据出去,直到网络恢复,或者超时不恢复就断线重连了。这是一个参考处理方法。还有一个参考处理方法就是给上层返回 EAGAIN,和TCP的方式一样,让用户去解决去。 |
当你需要发送“超过信道容量”的数据时,由易到烦,有三个处理方法。
理论上来讲,方法3在大多数情况下很有效果,但是如果你真的达到了信道的物理带宽上限,那么增加冗余包只会进一步增加丢包率。方法1和3都是缓解,归根结底是需要处理“每秒待发数据超过信道容量”这个问题,不管下层是tcp还是kcp,这个问题都必须要仔细处理。 |
谢谢耐心回复,这个问题我调了两天,所以代码读了不少,现在还在头疼,目前正常使用没啥问题,单子先关了 |
嗯,我看一下你的项目,没理解错的话,应该是一个代理,一头接受用户的tcp连接,一头使用kcp出去。这种代理类的完美解决方案是,如果你kcp的wait_send超过一个阀值T(比如64),那么停止用户tcp连接的recv,直到你每秒检测一次wait_send低于T/2了,那么再允许那条tcp连接的recv。这样发生网络抖动时,你不recv,用户又持续发数据,你tcp的recv_buf就会变满,接着用户进程连过来的tcp那端的snd_buf就会变满,然后用户的tcp socket就阻塞了,该继续缓存等待还是该断线重连就让用户来抉择了。这样的表现是和用户不用代理直接tcp到目的地时的效果一模一样。 |
好的谢谢 |
@vzex |
A B通讯,丢包率A:50%,B:75%
用脚本连续1000次请求发送一定数据
然后 kcp.snd_queue开始堆积
经过调试,发现是kcp.snd_buf队列中,segment.resendts延迟几乎每次都在100s后左右,导致snd_buf队列中的包一直很难发出,致使snd_una几乎不再更新
然后 _itimediff(kcp.snd_nxt, kcp.snd_una + cwnd) >= 0 这个条件基本上一直为true,最后snd_queue也开始堆积了。我用的版本是从c版本直接翻译成golang的,理论上行为全部一致,另外我看另外一个强制snd_buf发包的条件是包头的fastack大于0,但是这个也是依赖A发送B,B再回复ACK才会更新的,所以这个情况下基本上就是没有快速重试的途径,最后只能断开连接
我目前暂时的解决方案,snd_buff的第一个元素(影响snd_una更新的包)当xmit>2时强制重发,不知道有没有更合适的方法可以解决上面的问题?
The text was updated successfully, but these errors were encountered: