Пример #1
0
        protected virtual void SendData(byte[] data, int len)
        {
            if (connected)
            {
                uint new_conv = 0;
                KCP.ikcp_decode32u(data, 0, ref new_conv);
                Log.Error("send_cov=" + new_conv + ",time=" + GetCurrent());

                //查找有没有空闲的发送MySocketEventArgs,有就直接拿来用,没有就创建新的.So easy!
                MySocketEventArgs sendArgs = listArgs.Find(a => a.IsUsing == false);

                if (sendArgs == null)
                {
                    sendArgs = initSendArgs();
                }
                lock (sendArgs) //要锁定,不锁定让别的线程抢走了就不妙了.
                {
                    sendArgs.IsUsing = true;
                    sendArgs.SetBuffer(data, 0, len);
                }

                if (!clientSocket.SendToAsync(sendArgs))
                {
                    sendArgs.IsUsing = false;
                    ProcessSend(sendArgs);
                }
            }
            else
            {
                throw new SocketException((Int32)SocketError.NotConnected);
            }
        }
Пример #2
0
    void process_connect_packet()
    {
        mRecvQueue.Switch();

        if (!mRecvQueue.Empty())
        {
            var buf = mRecvQueue.Pop();

            UInt32 conv = 0;
            KCP.ikcp_decode32u(buf, 0, ref conv);

            if (conv <= 0)
            {
                throw new Exception("inlvaid connect back packet");
            }

            init_kcp(conv);

            mInConnectStage = false;
            mConnectSucceed = true;

            m_connectStatusCallback(NetworkState.Connected);
            //evHandler(cliEvent.Connected, null, null);
        }
    }
Пример #3
0
        void OnReceive(IAsyncResult ar)
        {
            try
            {
                if (ar.IsCompleted)
                {
                    IPEndPoint ipEndpoint = null;
                    byte[]     data       = client.EndReceive(ar, ref ipEndpoint);

                    if (!(data.Length < KCP.IKCP_OVERHEAD))
                    {
                        lock (kcpManager)
                        {
                            uint new_conv = 0;
                            KCP.ikcp_decode32u(data, 0, ref new_conv);

                            if (kcpManager.ContainsKey(new_conv))
                            {
                                kcpManager[new_conv].Input(data);
                            }
                        }
                    }
                }
            }
            catch (SocketException e)
            {
                // This happens when a client disconnects, as we fail to send to that port.
            }
            client.BeginReceive(OnReceive, null);
        }
Пример #4
0
        private void OnRecive(IAsyncResult ar)
        {
            if (client == null)
            {
                return;
            }

            try
            {
                byte[] buf = client.EndReceive(ar, ref remoteEndPoint);

                if (buf == null || buf.Length <= 0)
                {
                    Debug.LogError("Recive buff is null");
                    return;
                }

                if (buf.Length < KCP.IKCP_OVERHEAD)
                {
                    return;
                }

                UInt32 ts   = 0;
                UInt32 conv = 0;
                byte   cmd  = 0;

                KCP.ikcp_decode32u(buf, 0, ref conv);

                if (this.conv != conv)
                {
                    return;
                }

                KCP.ikcp_decode8u(buf, 4, ref cmd);

                if (cmd == KCP.IKCP_CMD_ACK)
                {
                    //拦截ack包中的时间戳,作为ping值计算
                    KCP.ikcp_decode32u(buf, 8, ref ts);
                    App.Trigger(EventName.Ping, (SystemTime.Clock() - ts));
                }

                //推进kcp处理
                channel.Input(buf);
                client.BeginReceive(OnRecive, null);
            }
            catch (Exception)
            {
                Debug.LogError("host is closed.");
                Dispose();
            }
        }
Пример #5
0
    /// <summary>
    /// 和Update同一个线程调用
    /// </summary>
    internal void process_recv_queue(byte[] datas)
    {
#if DEV
        IRQLog.AppLog.Log(this.m_netIndex.ToString() + ",接收1");
#endif
        if (m_Kcp != null && datas != null)
        {
            m_Kcp.Input(datas);

            m_NeedUpdateFlag = true;

            for (var size = m_Kcp.PeekSize(); size > 0; size = m_Kcp.PeekSize())
            {
                byte[] buffer;
                buffer = (UdpLibConfig.UseBytePool ? m_KCPServer.BytePool.Rent(size) : new byte[size]);
                try
                {
                    if (m_Kcp.Recv(buffer) > 0)
                    {
                        m_LastRecvTimestamp = m_KCPServer.m_watch.Elapsed;

                        uint key = 0;
                        KCP.ikcp_decode32u(buffer, 0, ref key);
                        if (m_KCPServer.IsClientKeyCorrect(this.m_netIndex, (int)key) == false)
                        {
#if DEBUG
                            Console.WriteLine("index:{0} key 不对", this.m_netIndex);
#endif
                            m_KCPServer.BytePool.Return(buffer, true);
                            DisposeReason = ClientSessionDisposeReason.IndexKeyError;
                            //key不对
                            Dispose();
                            return;
                        }
#if DEV
                        IRQLog.AppLog.Log(this.m_netIndex.ToString() + ",接收2");
#endif
                        m_KCPServer.OnRecvData(this, buffer, 0, size);
                    }
                }
                finally
                {
                    if (UdpLibConfig.UseBytePool)
                    {
                        m_KCPServer.BytePool.Return(buffer, true);
                    }
                }
            }
        }
    }
Пример #6
0
        public int Decode(byte[] buf, int size)
        {
            uint n = 0;

            KCP.ikcp_decode32u(buf, 0, ref n);
            if (n >= (uint)KcpCmd.KCP_CMD_COUNT)
            {
                return(-1);
            }
            cmd = (KcpCmd)n;
            if (cmd != KcpCmd.KCP_CMD_CONNECT_REQ)
            {
                KCP.ikcp_decode32u(buf, 4, ref conv);
            }
            return(0);
        }
Пример #7
0
        private void ProcessRecvQueue()
        {
            while (!RecvQueue.IsEmpty)
            {
                SocketAsyncEventArgs e = null;
                bool isSuccess         = RecvQueue.TryDequeue(out e);
                if (!isSuccess || e == null)
                {
                    continue;
                }
                if (e.BytesTransferred == 0)
                {
                    mSAEPool.PutObject(e);
                    continue;
                }
                //handshake with {0,0,0,0} at the first
                if (Helper.IsHandshakeDataRight(e.Buffer, e.Offset, e.BytesTransferred))
                {
                    uint conv       = Helper.iclock();
                    var  newSession = new KCPClientSession(conv);
                    newSession.ClientEndPoint  = e.RemoteEndPoint;
                    newSession.KCPOutput       = SendWithSession;
                    newSession.RecvDataHandler = RecvDataHandler;
                    mSessions.TryAdd(conv, newSession);

                    KCP.ikcp_encode32u(e.Buffer, e.BytesTransferred, conv);
                    e.SetBuffer(0, e.BytesTransferred + 4);
                    if (!mServerSocket.SendToAsync(e))
                    {
                        ProcessSend(e);
                    }
                    Console.WriteLine("Handshake from:" + e.RemoteEndPoint.ToString());
                }
                else
                {
                    uint conv = 0;
                    KCP.ikcp_decode32u(e.Buffer, e.Offset, ref conv);
                    KCPClientSession session = null;
                    mSessions.TryGetValue(conv, out session);
                    if (session != null)
                    {
                        session.processRecvQueue(e);
                    }
                    mSAEPool.PutObject(e);
                }
            }
        }
Пример #8
0
        // This method is invoked when an asynchronous receive operation completes.
        // If the remote host closed the connection, then the socket is closed.
        // If data was received then the data is echoed back to the client.
        //
        private void ProcessReceive(SocketAsyncEventArgs e)
        {
            try
            {
                Log.Error("EEE=" + e.BytesTransferred + "," + e.SocketError + "," + e.Count);

                if (e.BytesTransferred > 0 && e.SocketError == SocketError.Success)
                {
                    MySocketEventArgs eventArgs = this.receiveEventArgsPool.Rent <MySocketEventArgs>();
                    this.clientSocket.ReceiveFromAsync(eventArgs);

                    //读取数据
                    byte[] data = new byte[e.BytesTransferred];
                    Array.Copy(e.Buffer, e.Offset, data, 0, e.BytesTransferred);

                    if (!(data.Length < KCP.IKCP_OVERHEAD))
                    {
                        lock (kcpManager)
                        {
                            uint new_conv = 0;
                            KCP.ikcp_decode32u(data, 0, ref new_conv);

                            if (kcpManager.ContainsKey(new_conv))
                            {
                                kcpManager[new_conv].Input(data);
                            }
                        }
                    }

                    this.receiveEventArgsPool.Return((MySocketEventArgs)e);

                    /*
                     * if (!token.ReceiveFromAsync(e))
                     *  this.ProcessReceive(e);
                     */
                }
                else
                {
                    ProcessError(e);
                }
            }
            catch (Exception xe)
            {
                Console.WriteLine(xe.Message);
            }
        }
Пример #9
0
        /// <summary>
        /// 接收消息线程
        /// </summary>
        private void OnRecive(IAsyncResult ar)
        {
            try
            {
                remoteEndPoint = null;
                byte[] buf = client.EndReceive(ar, ref remoteEndPoint);

                //如果缓冲区为null 或 长度少于等于0,则断线
                if (buf == null || buf.Length <= 0)
                {
                    Dispose();
                    Debug.LogError("kcp buff is None");
                    return;
                }

                //获取会话conv
                UInt32 conv = 0;
                KCP.ikcp_decode32u(buf, 0, ref conv);

                //查找信道池,没有则建立新的

                KChannel channel;
                if (!channels.TryGetValue(conv, out channel))
                {
                    channel = new KChannel(conv, client, remoteEndPoint)
                    {
                        OnRecive = OnRecive
                    };
                    channel.OnConnectState = OnConnectState;
                    channels.Add(conv, channel);
                }

                channel.Input(buf);

                //再次调用异步接收
                client.BeginReceive(OnRecive, null);
            }
            catch (Exception)
            {
                //TODO 触发此处异常,一般由于客户端主动关闭致使S端无法返回数据包到C端。
                //TODO 服务器在此类异常中不需要关闭,只需要处理掉断开连接的C端
            }
        }
Пример #10
0
    /// <summary>
    /// 是否是正确的握手响应
    /// </summary>
    /// <param name="buffer"></param>
    /// <param name="offset"></param>
    /// <param name="size"></param>
    /// <param name="index"></param>
    /// <param name="key"></param>
    /// <returns></returns>
    internal static bool IsHandshakeDataRight(byte[] buffer, int offset, int size, out uint index, out uint key)
    {
        index = 0;
        key   = 0;
        if (size < UdpLibConfig.HandshakeDataSize)
        {
            return(false);
        }
        for (int i = 0; i < UdpLibConfig.HandshakeHeadData.Length; i++)
        {
            if (buffer[offset + i] != UdpLibConfig.HandshakeHeadData[i])
            {
                return(false);
            }
        }

        KCP.ikcp_decode32u(buffer, offset + UdpLibConfig.HandshakeHeadData.Length, ref index);
        KCP.ikcp_decode32u(buffer, offset + UdpLibConfig.HandshakeHeadData.Length + 4, ref key);
        return(true);
    }
Пример #11
0
        private void ProcessConnectQueue()
        {
            if (!recvQueue.IsEmpty)
            {
                byte[] data      = null;
                bool   isSuccess = recvQueue.TryDequeue(out data);
                if (!isSuccess || data == null)
                {
                    return;
                }

                if (Helper.IsHandshakeDataRight(data, 0, data.Length))
                {
                    UInt32 conv = 0;
                    KCP.ikcp_decode32u(data, Helper.HandshakeHeadData.Length, ref conv);
                    init_kcp(conv);
                    status = ClientStatus.Connected;
                    Console.WriteLine("Handshake Success");
                }
            }
        }
Пример #12
0
        protected void UpdateKcp()
        {
            while (connected)
            {
                long start = GetCurrent();
                lock (kcpManager)
                {
                    List <uint> pp = new List <uint>(kcpManager.Keys);

                    for (var index = 0; index < pp.Count; index++)
                    //foreach (KeyValuePair<uint, KCP> kv in kcpManager)
                    {
                        KeyValuePair <uint, KCP> kv = new KeyValuePair <uint, KCP>(pp[index], kcpManager[pp[index]]);
                        kv.Value.Update((uint)start);

                        int len = kv.Value.Recv(kcpDataCache);

                        if (len > 0)
                        {
                            byte[] data = new byte[len];
                            Array.Copy(kcpDataCache, data, len);
                            lock (m_buffer)
                            {
                                m_buffer.AddRange(data);
                            }

                            //DoReceiveEvent()
                            do
                            {
                                int headLength = Marshal.SizeOf(typeof(CommonPackHead));
                                // 判断包头是否满足
                                if (headLength <= m_buffer.Count)
                                {
                                    byte[] lenBytes = m_buffer.GetRange(0, headLength).ToArray();
                                    //分配结构体内存空间
                                    IntPtr structPtr = Marshal.AllocHGlobal(headLength);
                                    //将byte数组拷贝到分配好的内存空间
                                    Marshal.Copy(lenBytes, 0, structPtr, headLength);
                                    //将内存空间转换为目标结构体
                                    CommonPackHead packHead = (CommonPackHead)Marshal.PtrToStructure(structPtr, typeof(CommonPackHead));
                                    //释放内存空间
                                    Marshal.FreeHGlobal(structPtr);

                                    if (packHead.msg_len <= m_buffer.Count)
                                    {
                                        //包够长时,则提取出来,交给后面的程序去处理
                                        byte[] recv = m_buffer.GetRange(0, (int)packHead.msg_len).ToArray();

                                        lock (m_buffer)
                                        {
                                            m_buffer.RemoveRange(0, (int)packHead.msg_len);
                                        }
                                        //将数据包交给前台去处理
                                        DoReceiveEvent(packHead, recv);
                                    }
                                    else
                                    {
                                        break;
                                    }
                                }
                                else
                                {
                                    //
                                    if (4 == len)
                                    {
                                        uint new_conv = 0;
                                        KCP.ikcp_decode32u(data, 0, ref new_conv);

                                        if (!kcpManager.ContainsKey(new_conv))
                                        {
                                            kcpManager.Add(new_conv, new KCP(new_conv, SendData));
                                            lock (m_buffer)
                                            {
                                                m_buffer.RemoveRange(0, 4);
                                            }
                                        }

                                        usingConv = new_conv;
                                        Log.Error("usingConv=" + new_conv);
                                    }

                                    //长度不够,还得继续接收,需要跳出循环
                                    break;
                                }
                            } while (m_buffer.Count > 4);
                        }
                    }
                }
                long after = GetCurrent();
                if (after - start < ThreadGap)
                {
                    Thread.Sleep((int)(ThreadGap + start - after));
                }
            }
        }
Пример #13
0
        void ProcessRecvQueue(UInt32 now)
        {
            if (recvQueue_.Empty())
            {
                recvQueue_.Switch();
            }

            while (status_ == Status.Connected && !recvQueue_.Empty())
            {
                var buf = recvQueue_.Pop();


                UInt32 conv = 0;
                if (KCP.ikcp_decode32u(buf, 0, ref conv) < 0)
                {
                    // handle kcp command
                    continue;
                }

                if (conv < KcpConst.KCP_MIN_CONV)
                {
                    if (kcpCommand_.Decode(buf, buf.Length) < 0)
                    {
                        continue;
                    }

                    if (conv_ != kcpCommand_.conv)
                    {
                        continue;
                    }

                    lastRecvTime_ = now;
                    switch (kcpCommand_.cmd)
                    {
                    case KcpCmd.KCP_CMD_DISCONNECT: {
                        OnDisconnect();
                    }
                    break;

                    case KcpCmd.KCP_CMD_HEARTBEAT: {
                    }
                    break;
                    }
                }
                else
                {
                    if (conv_ != kcpCommand_.conv)
                    {
                        continue;
                    }
                    lastRecvTime_ = now;

                    kcp_.Input(buf);
                    needUpdate_ = true;

                    for (var size = kcp_.PeekSize(); size > 0; size = kcp_.PeekSize())
                    {
                        var buffer = new byte[size];
                        if (kcp_.Recv(buffer) > 0)
                        {
                            eventCallback_(conv, KcpEvent.KCP_EV_MSG, buffer, null);
                        }
                    }
                }
            }
        }
Пример #14
0
        // 测试用例
        static void KCPTest(int mode)
        {
            // 创建模拟网络:丢包率10%,Rtt 60ms~125ms
            vnet = new LatencySimulator(10, 60, 125);

            // 创建两个端点的 kcp对象,第一个参数 conv是会话编号,同一个会话需要相同
            // 最后一个是 user参数,用来传递标识
            var kcp1 = new KCP(0x11223344, 1);
            var kcp2 = new KCP(0x11223344, 2);

            // 设置kcp的下层输出,这里为 udp_output,模拟udp网络输出函数
            kcp1.SetOutput(udp_output);
            kcp2.SetOutput(udp_output);

            UInt32 current = Utils.iclock();
            UInt32 slap    = current + 20;
            UInt32 index   = 0;
            UInt32 next    = 0;
            Int64  sumrtt  = 0;
            int    count   = 0;
            int    maxrtt  = 0;

            // 配置窗口大小:平均延迟200ms,每20ms发送一个包,
            // 而考虑到丢包重发,设置最大收发窗口为128
            kcp1.WndSize(128, 128);
            kcp2.WndSize(128, 128);

            if (mode == 0) // 默认模式
            {
                kcp1.NoDelay(0, 10, 0, 0);
                kcp2.NoDelay(0, 10, 0, 0);
            }
            else if (mode == 1) // 普通模式,关闭流控等
            {
                kcp1.NoDelay(0, 10, 0, 1);
                kcp2.NoDelay(0, 10, 0, 1);
            }
            else // 启动快速模式
            {
                // 第1个参数 nodelay-启用以后若干常规加速将启动
                // 第2个参数 interval为内部处理时钟,默认设置为 10ms
                // 第3个参数 resend为快速重传指标,设置为2
                // 第4个参数 为是否禁用常规流控,这里禁止
                kcp1.NoDelay(1, 10, 2, 1);
                kcp2.NoDelay(1, 10, 2, 1);
                kcp1.SetMinRTO(10);
                kcp1.SetFastResend(1);
            }

            var    buffer = new byte[2000];
            int    hr     = 0;
            UInt32 ts1    = Utils.iclock();

            while (true)
            {
                Thread.Sleep(1);
                current = Utils.iclock();
                kcp1.Update(current);
                kcp2.Update(current);

                // 每隔 20ms,kcp1发送数据
                for (; current >= slap; slap += 20)
                {
                    KCP.ikcp_encode32u(buffer, 0, index++);
                    KCP.ikcp_encode32u(buffer, 4, current);

                    // 发送上层协议包
                    kcp1.Send(buffer, 0, 8);
                }

                // 处理虚拟网络:检测是否有udp包从p1->p2
                while (true)
                {
                    hr = vnet.Recv(1, buffer, 2000);
                    if (hr < 0)
                    {
                        break;
                    }

                    // 如果 p2收到udp,则作为下层协议输入到kcp2
                    hr = kcp2.Input(buffer, 0, hr);
                    Debug.Assert(hr >= 0);
                }

                // 处理虚拟网络:检测是否有udp包从p2->p1
                while (true)
                {
                    hr = vnet.Recv(0, buffer, 2000);
                    if (hr < 0)
                    {
                        break;
                    }

                    // 如果 p1收到udp,则作为下层协议输入到kcp1
                    hr = kcp1.Input(buffer, 0, hr);
                    Debug.Assert(hr >= 0);
                }

                // kcp2接收到任何包都返回回去
                while (true)
                {
                    hr = kcp2.Recv(buffer, 0, 10);
                    if (hr < 0)
                    {
                        break;
                    }

                    // 如果收到包就回射
                    hr = kcp2.Send(buffer, 0, hr);
                    Debug.Assert(hr >= 0);
                }

                // kcp1收到kcp2的回射数据
                while (true)
                {
                    hr = kcp1.Recv(buffer, 0, 10);
                    if (hr < 0) // 没有收到包就退出
                    {
                        break;
                    }

                    int    offset = 0;
                    UInt32 sn     = KCP.ikcp_decode32u(buffer, ref offset);
                    UInt32 ts     = KCP.ikcp_decode32u(buffer, ref offset);
                    UInt32 rtt    = current - ts;

                    if (sn != next)
                    {
                        // 如果收到的包不连续
                        Console.WriteLine(String.Format("ERROR sn {0}<->{1}", count, next));
                        return;
                    }
                    next++;
                    sumrtt += rtt;
                    count++;
                    if (rtt > maxrtt)
                    {
                        maxrtt = (int)rtt;
                    }

                    Console.WriteLine(String.Format("[RECV] mode={0} sn={1} rtt={2}", mode, sn, rtt));
                }
                if (next > 1000)
                {
                    break;
                }
            }
            ts1 = Utils.iclock() - ts1;
            var names = new string[3] {
                "default", "normal", "fast"
            };

            Console.WriteLine("{0} mode result ({1}ms):", names[mode], ts1);
            Console.WriteLine("avgrtt={0} maxrtt={1} tx={2}", sumrtt / count, maxrtt, vnet.tx1);
            Console.WriteLine("Press any key to next...");
            Console.Read();
        }
Пример #15
0
        // Test case
        static void KCPTest(int mode)
        {
            // Create an analog network: 10% packet loss rate,Rtt 60ms~125ms
            vnet = new LatencySimulator(10, 60, 125);

            // Create a kcp object with two endpoints, the first parameter conv is the session number, the same session needs to be the same
            // The last one is the user parameter, which is used to pass the identifier.
            var kcp1 = new KCP(0x11223344, 1);
            var kcp2 = new KCP(0x11223344, 2);

            // Set the lower output of kcp, here udp_output, simulate udp network output function
            kcp1.SetOutput(udp_output);
            kcp2.SetOutput(udp_output);

            UInt32 current = Utils.iclock();
            UInt32 slap    = current + 20;
            UInt32 index   = 0;
            UInt32 next    = 0;
            Int64  sumrtt  = 0;
            int    count   = 0;
            int    maxrtt  = 0;

            // Configuration window size: average delay 200ms, send a packet every 20ms,
            // Considering the packet loss retransmission, set the maximum receiving and sending window to 128.
            kcp1.WndSize(128, 128);
            kcp2.WndSize(128, 128);

            if (mode == 0)             //Default mode
            {
                kcp1.NoDelay(0, 10, 0, 0);
                kcp2.NoDelay(0, 10, 0, 0);
            }
            else if (mode == 1)             // Normal mode, turn off flow control, etc.
            {
                kcp1.NoDelay(0, 10, 0, 1);
                kcp2.NoDelay(0, 10, 0, 1);
            }
            else             //Start fast mode
            {
                // 1st parameter nodelay-enabled after some regular acceleration will start
                // The second parameter interval is the internal processing clock. The default setting is 10ms.
                // The third parameter resend is the fast retransmission indicator, set to 2
                // The fourth parameter is whether to disable regular flow control, this is forbidden here.
                kcp1.NoDelay(1, 10, 2, 1);
                kcp2.NoDelay(1, 10, 2, 1);
                kcp1.SetMinRTO(10);
                kcp1.SetFastResend(1);
            }

            var    buffer = new byte[2000];
            int    hr     = 0;
            UInt32 ts1    = Utils.iclock();

            while (true)
            {
                Thread.Sleep(1);
                current = Utils.iclock();
                kcp1.Update(current);
                kcp2.Update(current);

                // Kcp1 sends data every 20ms
                for (; current >= slap; slap += 20)
                {
                    KCP.ikcp_encode32u(buffer, 0, index++);
                    KCP.ikcp_encode32u(buffer, 4, current);

                    // Send the upper layer protocol packet
                    kcp1.Send(buffer, 0, 8);
                }

                //Handling virtual networks: detecting if there are udp packets from p1->p2
                while (true)
                {
                    hr = vnet.Recv(1, buffer, 2000);
                    if (hr < 0)
                    {
                        break;
                    }

                    //If p2 receives udp, it is input to kcp2 as the underlying protocol.
                    hr = kcp2.Input(buffer, 0, hr);
                    Debug.Assert(hr >= 0);
                }

                // Handling virtual networks: detecting if there are udp packets from p2->p1
                while (true)
                {
                    hr = vnet.Recv(0, buffer, 2000);
                    if (hr < 0)
                    {
                        break;
                    }

                    // If p1 receives udp, it is input to kcp1 as the underlying protocol.
                    hr = kcp1.Input(buffer, 0, hr);
                    Debug.Assert(hr >= 0);
                }

                // Kcp2 receives any package and returns it.
                while (true)
                {
                    hr = kcp2.Recv(buffer, 0, 10);
                    if (hr < 0)
                    {
                        break;
                    }

                    //If you receive the package, it will return
                    hr = kcp2.Send(buffer, 0, hr);
                    Debug.Assert(hr >= 0);
                }

                // Kcp1 receives the echo data of kcp2
                while (true)
                {
                    hr = kcp1.Recv(buffer, 0, 10);
                    if (hr < 0)                     // Exit without receiving the package
                    {
                        break;
                    }

                    int    offset = 0;
                    UInt32 sn     = KCP.ikcp_decode32u(buffer, ref offset);
                    UInt32 ts     = KCP.ikcp_decode32u(buffer, ref offset);
                    UInt32 rtt    = current - ts;

                    if (sn != next)
                    {
                        // If the received packet is not continuous
                        Console.WriteLine(String.Format("ERROR sn {0}<->{1}", count, next));
                        return;
                    }
                    next++;
                    sumrtt += rtt;
                    count++;
                    if (rtt > maxrtt)
                    {
                        maxrtt = (int)rtt;
                    }

                    Console.WriteLine(String.Format("[RECV] mode={0} sn={1} rtt={2}", mode, sn, rtt));
                }
                if (next > 1000)
                {
                    break;
                }
            }
            ts1 = Utils.iclock() - ts1;
            var names = new string[3] {
                "default", "normal", "fast"
            };

            Console.WriteLine("{0} mode result ({1}ms):", names[mode], ts1);
            Console.WriteLine("avgrtt={0} maxrtt={1} tx={2}", sumrtt / count, maxrtt, vnet.tx1);
            Console.WriteLine("Press any key to next...");
            Console.Read();
        }
Пример #16
0
    private void DealData(IPEndPoint RemoteEndPoint, byte[] buffer)
    {
        try
        {
            uint index = 0, key = 0;
            if (IsHandshake(buffer, 0, buffer.Length, out index, out key))
            {//先握手,使用纯udp进行握手,8字节0xFF+4字节conv+4字节key
                var  c  = GetSession(index);
                uint cc = 0;
                KCP.ikcp_decode32u(buffer, 16, ref cc);
                if (c == null)
                {
                    bool add = true;
                    //新连接处理,如果返回false,则不予处理,可以用来进行非法连接的初步处理
                    if (NewSessionProcessor != null)
                    {
                        add = NewSessionProcessor.OnNewSession(index, RemoteEndPoint);
                    }
                    if (add == false)
                    {
                        return;
                    }
                    c                     = AddSession(RemoteEndPoint, index);
                    c.m_KCPServer         = this;
                    c.m_LastRecvTimestamp = m_watch.Elapsed;
                    OnNewClientSession(c, buffer, 0, buffer.Length);
                }
                else
                {
                    Log.Info("====重新设置EndPoint====");
                    c.EndPoint = RemoteEndPoint;
                    //如果客户端关闭并且立刻重连,这时候是连不上的,因为KCP中原有的数据不能正确处理
                    //c.ResetKCP();
                }

                c.Status = ClientSessionStatus.Connected;
                //回发握手请求
                UDPClient.BeginSend(buffer, buffer.Length, RemoteEndPoint, (IAsyncResult iar) => { UDPClient.EndSend(iar); }, null);
            }
            else
            {
                try
                {
                    KCP.ikcp_decode32u(buffer, 0, ref index);
                    var c = GetSession(index);
                    if (c != null && c.Status == ClientSessionStatus.Connected)
                    {
                        //Debug.Assert(c.EndPoint.ToString() == RemoteEndPoint.ToString());
                        if (c.EndPoint.ToString() != RemoteEndPoint.ToString())
                        {
                            c.EndPoint = RemoteEndPoint;
                            Log.Error("==ClientSessionStatus.Connected==");
                        }
                        c.AddRecv(buffer);
                    }
                }
                catch (Exception ex)
                {
                    Log.Error("==DealData error:" + ex.ToString());
                }
            }
        }
        catch (Exception ex)
        {
            Log.Error("DealData Error:" + ex.ToString());
        }
    }