Skip to content
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

丢包率为1%时候,有时候延迟会变得越来越大,无法恢复 #93

Closed
adzhang opened this issue Aug 14, 2017 · 4 comments
Closed

Comments

@adzhang
Copy link

adzhang commented Aug 14, 2017

image

这是我用tc命令设置服务器网络有1%的丢包率时候测的
tc qdisc add dev eth1 root netem delay 0ms 10ms 1% loss 1%

测试程序每秒30次地随机发送100、200、400Byte大小的数据,发现kcp偶尔会出现延迟不断变大再也无法恢复。测试程序使用python ctypes直接调用kcp编译出来的动态库,一般时候表现良好。

主要用了下面这些参数
libkcp.ikcp_nodelay(self._kcp, 1, 10, 2, 1)
libkcp.ikcp_wndsize(self._kcp, 2048, 2048)

def update(self, now_time):
ikcp_update(self._kcp, c_int(int(now_time*1000)))

    if self._socket:
        while True:
            try:
                data = self._receive_msg_queue.get_nowait()
                err = ikcp_input(self._kcp, data[0], len(data[0]))
                if err < 0:
                    print "[WORNNING] ikcp_input error:", err
                    break
            except Queue.Empty:
                break

        while True:
            n = ikcp_recv(self._kcp, byref(self._data_buf), self._data_buf_size)
            if n > 0:
                self.on_data(self._data_buf[:n])
            else:
                break

问下什么情况可能导致这种现象,需要怎么避免?可能的话可以把测试程序和测试方法发过去。

@skywind3000
Copy link
Owner

基础知识啊,这叫缓存积累延迟,请检测 ikcp_waitsnd,发送端超过一定阈值就不要调用 ikcp_send了,
就跟你 tcp 没能力发送却一直调用send,超过socket sndbuf,系统会返回你 EAGAIN/EWOULDBLOCK一样。

你已经没能力发送了,还持续不断的追加数据到 sndbuf,当然会越来越慢,你总不可能幻想无止尽调用 ikcp_send 对方都能实时收到吧?那你这不突破物理带宽极限了?

可用带宽 = min(本地发送窗口字节尺寸, 远端可用接收窗口字节尺寸) x (1 - 丢包率) / RTT

你只有两个解决方法:

  1. 检测 ikcp_waitsnd,超过阈值就当做 EAGAIN / EWOULDBLOCK处理,不要继续发送。
  2. 增加发送方 SND_WND, 接收方 RCV_WND,默认是32,比如你可以调节成 256。

你们看看 TCP网络编程相关资料吧,但凡知道 EAGAIN / EWOULDBLOCK 是怎么回事情的人都不会无止境的调用 send。

@adzhang
Copy link
Author

adzhang commented Aug 15, 2017

感谢你的解答!

libkcp.ikcp_wndsize(self._kcp, 2048, 2048)
我这边把窗口都调成2048了,出现的频率会减少,因为我这边预估的数据量和发送频率应该是极限了,三个测试程序都是跑同样的数据量,kcp会容易出现这种过载无法恢复,或者有很长时间的高延迟后恢复,把发送数据改小也不管用。看来我必须要为kcp再做一个缓冲区缓冲一下发送频率了。

@skywind3000
Copy link
Owner

TCP,Windows 下,默认 SNDBUF 8KB,每秒30次,每次400字节,1%的丢包,RTT稍微大点,20多秒也就BLOCK掉了。

@hubinix
Copy link

hubinix commented Sep 4, 2017

不是发送频率的问题,是ack报文丢了的缘故。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants