public Exception Connect() { udpClient = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); udpClient.Bind(new IPEndPoint(IPAddress.Parse("0.0.0.0"), udpPort)); recIEpoint = new IPEndPoint(IPAddress.Parse("0.0.0.0"), udpPort); sndIEpoint = new IPEndPoint(IPAddress.Parse(udpIp), udpPort); // 创建KCP实例 session = (uint)(new Random(DateTime.Now.Millisecond).Next(1, Int32.MaxValue)) + 1; mKCP = new KCP(session, rawSend); // 设置kcp模式 // normal: 0, 40, 2, 1 // fast: 0, 30, 2, 1 // fast2: 1, 20, 2, 1 // fast3: 1, 10, 2, 1 mKCP.NoDelay(nodelay, interval, resend, nc); mKCP.SetStreamMode(streamMode); // 设置接收和发送窗大小, 默认都为128 mKCP.WndSize(sndwnd, recwnd); // 设置冗余长度,默认不使用冗余 if (redlen > 0) { redData = new List <byte> [redlen]; Array.Clear(redData, 0, redlen); int maxdatalen = redlen + recwnd; int bitmaplen = maxdatalen >> 3; if (maxdatalen > bitmaplen << 3) { bitmaplen++; } redbitmap = new byte[bitmaplen]; // 初始化冗余数据buffer redBuffer = new byte[redlen + 1][]; for (int i = 0; i < redlen + 1; i++) { redBuffer[i] = new byte[256]; } } // 启动更新定时器 if (writeDelay > 0) { updateTimer = new Timer(new TimerCallback(kcpUpdate), null, Timeout.Infinite, Timeout.Infinite); } protocolRun = true; return(null); }
// 处理接收冗余 private int redRevFmt(byte[] data, int offset, int kcplen) { int pnum = 0; int pDataLen = 0; UInt32 sn = 0, csn; KCP.ikcp_decode32u(data, offset + 12, ref sn); int rIndex = 24 + offset; if (data[rIndex] == 0xff) { rIndex += 1; } for (UInt32 i = 0; i < (redlen + 1); i++) { if (i == 0 && (data[24 + offset] != 0xff || data[offset + 5] > 0)) { pDataLen = kcplen - rIndex + offset; } else { pDataLen = (((int)data[rIndex]) << 8) + data[rIndex + 1] + 2; } csn = sn - i; // 验证是否已被接收,第一个包只记录不做验证 if (i >= 1) { if (csn < minredidx) { break; } if (chkBitmap(csn)) { continue; } if (pDataLen <= 2) { continue; } } if (redBuffer[i].Length < 24 + pDataLen) { redBuffer[i] = new byte[24 + pDataLen]; } Array.Copy(data, offset, redBuffer[i], 0, 24); Array.Copy(data, rIndex, redBuffer[i], 24, pDataLen); // 修改包数据 KCP.ikcp_encode32u(redBuffer[i], 12, csn); KCP.ikcp_encode32u(redBuffer[i], 20, (uint)pDataLen); rIndex += pDataLen; pnum++; setBitmap(csn, true); if (minredidx == csn) { while (chkBitmap(minredidx)) { // 设置为1 setBitmap(minredidx, false); // 检查下一个是否提交,提交继续往前累加 minredidx++; } } if (rIndex >= kcplen + offset) { break; } } return(pnum); }