/// <summary> /// 将buff构建成kcp包 /// </summary> /// <param name="buf"></param> /// <param name="len"></param> /// <param name="kcp"></param> /// <param name="user"></param> /// <returns></returns> protected int Output(sbyte *buf, int len, IKCPCB *kcp, void *user) { byte[] kcppack = new byte[len]; Marshal.Copy(new IntPtr(buf), kcppack, 0, len); OutgoingData.Enqueue(kcppack); return(0); }
public void CreateKcp(uint clientid) { if (kcp == null) { var errno = ikcp_create(clientid, (void *)0); if ((int)errno != -1) { kcp = errno; /*该调用将会设置协议的最大发送窗口和最大接收窗口大小,默认为32. 这个可以理解为 TCP的 SND_BUF 和 RCV_BUF,只不过单位不一样 SND/RCV_BUF 单位是字节,这个单位是包。*/ ikcp_wndsize(kcp, this.options.SndWindowSize, this.options.RecWindowSize); /* * nodelay :是否启用 nodelay模式,0不启用;1启用。 * interval :协议内部工作的 interval,单位毫秒,比如 10ms或者 20ms * resend :快速重传模式,默认0关闭,可以设置2(2次ACK跨越将会直接重传) * nc :是否关闭流控,默认是0代表不关闭,1代表关闭。 * 普通模式:`ikcp_nodelay(kcp, 0, 40, 0, 0); * 极速模式: ikcp_nodelay(kcp, 1, 10, 2, 1); */ ikcp_nodelay(kcp, this.options.NoDelay, this.options.NoDelayInterval, this.options.NoDelayResend, this.options.NoDelayNC); /*最大传输单元:纯算法协议并不负责探测 MTU,默认 mtu是1400字节,可以使用ikcp_setmtu来设置该值。该值将会影响数据包归并及分片时候的最大传输单元。*/ int mtu = Math.Min(this.options.MAX_DATA_LEN, this.options.MTU); ikcp_setmtu(kcp, mtu);//可能还要浪费几个字节 /*最小RTO:不管是 TCP还是 KCP计算 RTO时都有最小 RTO的限制,即便计算出来RTO为40ms,由于默认的 RTO是100ms,协议只有在100ms后才能检测到丢包,快速模式下为30ms,可以手动更改该值:*/ kcp->rx_minrto = this.options.RTO; } else { kcp = null; throw new InvalidCastException($"kcp create failed {(int)errno}"); } } }
public void Stop() { if (!this.IsRunning) { return; } this.IsRunning = false; if (kcp != null) { Console.WriteLine($"release kcp {(int)kcp}"); ikcp_release(kcp); kcp = null; } }
protected override unsafe int udp_output(byte *buf, int len, IKCPCB *kcp, void *user) { byte[] buff = new byte[len + 1]; Marshal.Copy(new IntPtr(buf), buff, 1, len); #if PRINTPACK printpack($"kcp_output:{buff.Length}:{string.Join(",",buff)}"); #endif buff[0] = (byte)Utilities.PackType.Kcp; if (Outgoing != null) { Outgoing.Enqueue(buff); } return(0); }
public static extern void ikcp_update(IKCPCB *kcp, uint current);
public static extern int ikcp_send(IKCPCB *kcp, byte *buffer, int len);
public static extern void ikcp_setoutput(IKCPCB *kcp, IntPtr d_output);
public static extern void ikcp_release(IKCPCB *kcp);
public static extern void ikcp_log(IKCPCB *kcp, int mask, byte *fmt, params object[] p);
public static extern int ikcp_nodelay(IKCPCB *kcp, int nodelay, int interval, int resend, int nc);
public static extern int ikcp_wndsize(IKCPCB *kcp, int sndwnd, int rcvwnd);
public static extern int ikcp_setmtu(IKCPCB *kcp, int mtu);
public static extern int ikcp_peeksize(IKCPCB *kcp);
public static extern void ikcp_flush(IKCPCB *kcp);
public static extern uint ikcp_check(IKCPCB *kcp, uint current);
public static extern int ikcp_input(IKCPCB *kcp, byte *data, long size);
public static extern int ikcp_waitsnd(IKCPCB *kcp);