Beispiel #1
0
        public void Connect(string host, int port)
        {
            if (m_Dispose)
            {
                throw new ObjectDisposedException("ClientSocket already dispose!");
            }

            if (IsConnected)
            {
                Logger.Error($"已连接 {host}:{port}");
                return;
            }

            if (m_Status == Status.Connecting)
            {
                Logger.Error($"正在连接中 {host}:{port}");
                return;
            }

            m_Status = Status.Connecting;

            IPAddress[] addresses = Dns.GetHostAddresses(host);

            if (addresses.Length < 1)
            {
                throw new ArgumentException($"不能解析的地址:{host}");
            }

            IPEndPoint point = new IPEndPoint(addresses[0], port);

            m_Socket = new Socket(point.AddressFamily, SocketType.Dgram, ProtocolType.Udp);
            KcpHelper.CreateThread(OnConnectLooper, point);
        }
Beispiel #2
0
        public void Output(Memory <byte> memory, int length)
        {
            if (m_Dispose)
            {
                return;
            }

            KcpHelper.Encode32u(m_OutputBuffer, 0, m_ConId);
            m_OutputBuffer[KcpConstants.Conv_Size] = MsgChannel.Reliable;
            memory.Span.Slice(0, length).CopyTo(new Span <byte>(m_OutputBuffer, KcpConstants.Head_Size, length));

            OnSendData(m_OutputBuffer, 0, length + KcpConstants.Head_Size);
        }
Beispiel #3
0
        public void Bind(int port, IChannelListener listener)
        {
            if (m_Dispose)
            {
                throw new ObjectDisposedException("ServerTransport already disposed!");
            }

            m_Listener = listener;
            m_Socket   = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
            m_Socket.Bind(new IPEndPoint(IPAddress.Any, port));

            KcpHelper.CreateThread(RecvUdpDataLooper);
            KcpHelper.CreateThread(UpdateChannelLooper);
        }
Beispiel #4
0
        public int RawSend(byte[] buffer, int offset, int length)
        {
            if (m_Dispose)
            {
                return(-10);
            }

            KcpHelper.Encode32u(m_OutputBuffer, 0, m_ConId);
            m_OutputBuffer[KcpConstants.Conv_Size] = MsgChannel.Unreliable;
            Array.Copy(buffer, offset, m_OutputBuffer, KcpConstants.Head_Size, length);

            OnSendData(m_OutputBuffer, 0, length + KcpConstants.Conv_Size + 1);

            return(length + KcpConstants.Head_Size);
        }
Beispiel #5
0
        private void RecvUdpDataLooper(object obj)
        {
            try
            {
                uint          startConvId = 10000;
                const int     pollTimeout = 100000;
                List <Packet> packets     = new List <Packet>();
                byte[]        rawBuffer   = new byte[KcpConstants.Packet_Length];
                EndPoint      remote      = new IPEndPoint(IPAddress.Any, 0);

                while (!m_Dispose)
                {
                    if (!m_Socket.Poll(pollTimeout, SelectMode.SelectRead))
                    {
                        continue;
                    }

                    if (m_Dispose)
                    {
                        break;
                    }

                    int size = m_Socket.ReceiveFrom(rawBuffer, SocketFlags.None, ref remote);
                    if (size > 0)
                    {
                        uint cid = (uint)remote.GetHashCode();
                        if (!m_Channels.TryGetValue(cid, out ServerChannel channel))
                        {
                            if (size == 4)
                            {
                                uint flag = KcpHelper.Decode32u(rawBuffer, 0);
                                if (flag == KcpConstants.Flag_Connect)
                                {
                                    uint     conv  = startConvId++;
                                    EndPoint point = remote.Create(remote.Serialize());
                                    channel = new ServerChannel(new KcpConServer(cid, conv, m_Socket, point));

                                    if (m_Channels.TryAdd(cid, channel))
                                    {
                                        KcpHelper.Encode32u(rawBuffer, 0, KcpConstants.Flag_Connect);
                                        KcpHelper.Encode32u(rawBuffer, 4, conv);
                                        channel.Send(rawBuffer, 0, 8);
                                        channel.Flush();
                                    }
                                }
                            }
                            else
                            {
                                Logger.Error($"not connect size={size}");
                            }
                        }
                        else if (size > KcpConstants.Head_Size)
                        {
                            uint remoteCid = KcpHelper.Decode32u(rawBuffer, 0);
                            if (cid == remoteCid)
                            {
                                byte msgChannel = rawBuffer[KcpConstants.Conv_Size];
                                if (msgChannel == MsgChannel.Reliable)
                                {
                                    channel.Input(rawBuffer, KcpConstants.Head_Size, size - KcpConstants.Head_Size);
                                    channel.RecvReliablePackets(m_Process, packets, m_Listener);
                                }
                                else if (msgChannel == MsgChannel.Unreliable)
                                {
                                    channel.RecvUnreliablePackets(rawBuffer, KcpConstants.Head_Size, size - KcpConstants.Head_Size, m_Process, packets);
                                }
                            }
                            else
                            {
                                Logger.Error($"conv {cid} != {remoteCid}");
                            }
                        }
                        else
                        {
                            Logger.Error($"size={size} < {KcpConstants.Head_Size}");
                        }
                    }
                }
            }
            catch (Exception e)
            {
                Logger.Error(e.ToString());
            }
        }
Beispiel #6
0
        private void OnHandleLooper(object obj)
        {
            try
            {
                List <Packet>             packets   = new List <Packet>();
                byte[]                    rawBuffer = new byte[KcpConstants.Packet_Length];
                ClientDataProcessing      process   = new ClientDataProcessing();
                ClientHeartbeatProcessing heartbeat = new ClientHeartbeatProcessing();

                while (!m_Dispose && m_Status == Status.Success)
                {
                    if (m_SendPackets.Count > 0)
                    {
                        process.SendPackets(m_Kcp, m_SendPackets);
                    }

                    long time = TimeUtils.Get1970ToNowMilliseconds();
                    m_Kcp.OnUpdate(time);
                    heartbeat.UpdateHeartbeat(this, m_Kcp, time);

                    while (m_Socket.Poll(0, SelectMode.SelectRead))
                    {
                        int count = m_Socket.Receive(rawBuffer, 0, rawBuffer.Length, SocketFlags.None);

                        if (count > KcpConstants.Head_Size)
                        {
                            uint remoteCid = KcpHelper.Decode32u(rawBuffer, 0);
                            if (remoteCid == m_Kcp.ConId)
                            {
                                byte msgChannel = rawBuffer[KcpConstants.Conv_Size];

                                if (msgChannel == MsgChannel.Reliable)
                                {
                                    m_Kcp.Input(rawBuffer, KcpConstants.Head_Size, count - KcpConstants.Head_Size);
                                    process.RecvReliablePackets(this, m_Kcp, packets, heartbeat);
                                }
                                else if (msgChannel == MsgChannel.Unreliable)
                                {
                                    process.RecvUnreliablePackets(rawBuffer, KcpConstants.Head_Size, count - KcpConstants.Head_Size, packets);
                                }

                                int length = packets.Count;
                                if (length > 0)
                                {
                                    for (int i = 0; i < length; ++i)
                                    {
                                        m_RecvPackets.Enqueue(packets[i]);
                                    }
                                    packets.Clear();
                                }
                            }
                        }
                    }

                    Thread.Sleep(5);
                }
            }
            catch (Exception e)
            {
                Logger.Error(e.ToString());
                if (m_Status == Status.Success)
                {
                    m_Status = Status.Disconnect;
                }
            }
            finally
            {
                if (!m_Dispose)
                {
                    if (m_Status == Status.Disconnect)
                    {
                        m_Register.Notify(Msg.Disconnect);
                    }
                }
            }
        }
Beispiel #7
0
        private void OnConnectLooper(object point)
        {
            try
            {
                int       time        = 0;
                const int tick        = 100;
                const int timeout     = 5000;
                const int pollTimeout = 100000;
                byte[]    rawBuffer   = new byte[KcpConstants.Packet_Length];

                m_Socket.Connect((EndPoint)point);

                while (!m_Dispose && m_Status == Status.Connecting)
                {
                    int size = KcpHelper.Encode32u(rawBuffer, 0, KcpConstants.Flag_Connect);
                    m_Socket.Send(rawBuffer, 0, size, SocketFlags.None);

                    if (!m_Socket.Poll(pollTimeout, SelectMode.SelectRead))
                    {
                        time += tick;
                        if (time >= timeout)
                        {
                            m_Status = Status.Timeout;
                            break;
                        }
                        continue;
                    }

                    if (m_Dispose)
                    {
                        break;
                    }

                    int count = m_Socket.Receive(rawBuffer, 0, rawBuffer.Length, SocketFlags.None);

                    if (count == 37)
                    {
                        uint cid  = KcpHelper.Decode32u(rawBuffer, 0);
                        uint flag = KcpHelper.Decode32u(rawBuffer, 29);
                        uint conv = KcpHelper.Decode32u(rawBuffer, 33);

                        if (flag == KcpConstants.Flag_Connect)
                        {
                            m_Kcp = new KcpConClient(cid, conv, m_Socket);
                            m_Kcp.Input(rawBuffer, KcpConstants.Head_Size, count - KcpConstants.Head_Size);
                            count = m_Kcp.Recv(rawBuffer, 0, rawBuffer.Length);

                            if (count == 8)
                            {
                                KcpHelper.Encode32u(rawBuffer, 0, KcpConstants.Flag_Connect);
                                KcpHelper.Encode32u(rawBuffer, 4, conv);
                                m_Kcp.Send(rawBuffer, 0, 8);
                                m_Kcp.Flush();

                                m_ConId  = cid;
                                m_Status = Status.Success;
                                m_Register.Notify(Msg.Success);

                                KcpHelper.CreateThread(OnHandleLooper);
                                break;
                            }
                        }
                    }
                }
            }
            catch (Exception e)
            {
                Logger.Error(e.ToString());
                m_Status = Status.Error;
            }
            finally
            {
                if (!m_Dispose)
                {
                    if (m_Status == Status.Error)
                    {
                        m_Register.Notify(Msg.Error);
                    }
                    else if (m_Status == Status.Timeout)
                    {
                        m_Register.Notify(Msg.Timeout);
                    }
                }
            }
        }