Beispiel #1
0
        public void HandleRecv(byte[] date, int offset, int length)
        {
            if (this.IsDisposed)
            {
                return;
            }

            this.isConnected = true;

            Kcp.KcpInput(this.kcp, date, offset, length);
            this.GetService().AddToUpdateNextTime(0, this.Id);

            while (true)
            {
                if (this.IsDisposed)
                {
                    return;
                }
                int n = Kcp.KcpPeeksize(this.kcp);
                if (n < 0)
                {
                    return;
                }
                if (n == 0)
                {
                    this.OnError((int)SocketError.NetworkReset);
                    return;
                }

                byte[] buffer = this.memoryStream.GetBuffer();
                this.memoryStream.SetLength(n);
                this.memoryStream.Seek(0, SeekOrigin.Begin);
                int count = Kcp.KcpRecv(this.kcp, buffer, ushort.MaxValue);
                if (n != count)
                {
                    return;
                }
                if (count <= 0)
                {
                    return;
                }

                this.lastRecvTime = this.GetService().TimeNow;

                this.OnRead(this.memoryStream);
            }
        }
Beispiel #2
0
        public void Update()
        {
            if (this.IsDisposed)
            {
                return;
            }

            uint timeNow = this.Service.TimeNow;

            // 如果还没连接上,发送连接请求
            if (!this.IsConnected)
            {
                // 20秒没连接上则报错
                if (timeNow - this.CreateTime > 10 * 1000)
                {
                    Log.Error($"kChannel connect timeout: {this.Id} {this.RemoteConn} {timeNow} {this.CreateTime} {this.ChannelType} {this.RemoteAddress}");
                    this.OnError(ErrorCode.ERR_KcpConnectTimeout);
                    return;
                }

                switch (ChannelType)
                {
                case ChannelType.Connect:
                    this.Connect();
                    break;
                }
                return;
            }

            try
            {
                Kcp.KcpUpdate(this.kcp, timeNow);
            }
            catch (Exception e)
            {
                Log.Error(e);
                this.OnError(ErrorCode.ERR_SocketError);
                return;
            }

            if (this.kcp != IntPtr.Zero)
            {
                uint nextUpdateTime = Kcp.KcpCheck(this.kcp, timeNow);
                this.Service.AddToUpdateNextTime(nextUpdateTime, this.Id);
            }
        }
Beispiel #3
0
        // accept
        public KChannel(long id, uint localConn, uint remoteConn, Socket socket, IPEndPoint remoteEndPoint, KService kService)
        {
            this.Id          = id;
            this.ChannelType = ChannelType.Accept;

            Log.Info($"channel create: {this.Id} {localConn} {remoteConn} {remoteEndPoint} {this.ChannelType}");

            this.Service       = kService;
            this.LocalConn     = localConn;
            this.RemoteConn    = remoteConn;
            this.RemoteAddress = remoteEndPoint;
            this.socket        = socket;
            this.kcp           = Kcp.KcpCreate(this.RemoteConn, IntPtr.Zero);
            this.InitKcp();

            this.lastRecvTime = kService.TimeNow;
            this.CreateTime   = kService.TimeNow;
        }
Beispiel #4
0
        // accept
        public KChannel(uint localConn, uint remoteConn, Socket socket, IPEndPoint remoteEndPoint, KService kService) : base(kService, ChannelType.Accept)
        {
            this.memoryStream = this.GetService().MemoryStreamManager.GetStream("message", ushort.MaxValue);

            this.LocalConn      = localConn;
            this.RemoteConn     = remoteConn;
            this.remoteEndPoint = remoteEndPoint;
            this.socket         = socket;
            this.kcp            = Kcp.KcpCreate(this.RemoteConn, new IntPtr(this.LocalConn));

            SetOutput();
            Kcp.KcpNodelay(this.kcp, 1, 10, 1, 1);
            Kcp.KcpWndsize(this.kcp, 256, 256);
            Kcp.KcpSetmtu(this.kcp, 470);
            this.lastRecvTime = kService.TimeNow;
            this.createTime   = kService.TimeNow;
            this.Accept();
        }
Beispiel #5
0
        private void InitKcp()
        {
            switch (this.Service.ServiceType)
            {
            case ServiceType.Inner:
                Kcp.KcpNodelay(kcp, 1, 10, 2, 1);
                Kcp.KcpWndsize(kcp, 1024 * 100, 1024 * 100);
                Kcp.KcpSetmtu(kcp, 1400);                         // 默认1400
                Kcp.KcpSetminrto(kcp, 10);
                break;

            case ServiceType.Outer:
                Kcp.KcpNodelay(kcp, 1, 10, 2, 1);
                Kcp.KcpWndsize(kcp, 128, 128);
                Kcp.KcpSetmtu(kcp, 470);
                Kcp.KcpSetminrto(kcp, 10);
                break;
            }
        }
Beispiel #6
0
        private void KcpSend(KcpWaitPacket kcpWaitPacket)
        {
            if (this.IsDisposed)
            {
                return;
            }

            MemoryStream memoryStream = kcpWaitPacket.MemoryStream;

            if (this.Service.ServiceType == ServiceType.Inner)
            {
                memoryStream.GetBuffer().WriteTo(0, kcpWaitPacket.ActorId);
            }

            int count = (int)(memoryStream.Length - memoryStream.Position);

            Kcp.KcpSend(this.kcp, memoryStream.GetBuffer(), (int)memoryStream.Position, count);
            this.Service.AddToUpdateNextTime(0, this.Id);
        }
Beispiel #7
0
        private void KcpSend(KcpWaitPacket kcpWaitPacket)
        {
            if (this.IsDisposed)
            {
                return;
            }

            MemoryStream memoryStream = kcpWaitPacket.MemoryStream;
            int          count        = (int)(memoryStream.Length - memoryStream.Position);

            if (this.Service.ServiceType == ServiceType.Inner)
            {
                memoryStream.GetBuffer().WriteTo(0, kcpWaitPacket.ActorId);
            }

            // 超出maxPacketSize需要分片
            if (count <= maxPacketSize)
            {
                Kcp.KcpSend(this.kcp, memoryStream.GetBuffer(), (int)memoryStream.Position, count);
            }
            else
            {
                // 先发分片信息
                this.sendCache.WriteTo(0, 0);
                this.sendCache.WriteTo(4, count);
                Kcp.KcpSend(this.kcp, this.sendCache, 0, 8);

                // 分片发送
                int alreadySendCount = 0;
                while (alreadySendCount < count)
                {
                    int leftCount = count - alreadySendCount;

                    int sendCount = leftCount < maxPacketSize? leftCount: maxPacketSize;

                    Kcp.KcpSend(this.kcp, memoryStream.GetBuffer(), (int)memoryStream.Position + alreadySendCount, sendCount);

                    alreadySendCount += sendCount;
                }
            }

            this.Service.AddToUpdateNextTime(0, this.Id);
        }
Beispiel #8
0
        public void Send(long actorId, MemoryStream stream)
        {
            if (this.kcp != IntPtr.Zero)
            {
                // 检查等待发送的消息,如果超出最大等待大小,应该断开连接
                int n = Kcp.KcpWaitsnd(this.kcp);

                int maxWaitSize = 0;
                switch (this.Service.ServiceType)
                {
                case ServiceType.Inner:
                    maxWaitSize = Kcp.InnerMaxWaitSize;
                    break;

                case ServiceType.Outer:
                    maxWaitSize = Kcp.OuterMaxWaitSize;
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }

                if (n > maxWaitSize)
                {
                    Log.Error($"kcp wait snd too large: {n}: {this.Id} {this.RemoteConn}");
                    this.OnError(ErrorCode.ERR_KcpWaitSendSizeTooLarge);
                    return;
                }
            }

            KcpWaitPacket kcpWaitPacket = new KcpWaitPacket()
            {
                ActorId = actorId, MemoryStream = stream
            };

            if (!this.IsConnected)
            {
                this.sendBuffer.Enqueue(kcpWaitPacket);
                return;
            }
            this.KcpSend(kcpWaitPacket);
        }
Beispiel #9
0
        private void InitKcp()
        {
            KcpPtrChannels.Add(this.kcp, this);
            switch (this.Service.ServiceType)
            {
            case ServiceType.Inner:
                Kcp.KcpNodelay(kcp, 1, 10, 2, 1);
                Kcp.KcpWndsize(kcp, ushort.MaxValue, ushort.MaxValue);
                Kcp.KcpSetmtu(kcp, 1400);                         // 默认1400
                Kcp.KcpSetminrto(kcp, 30);
                break;

            case ServiceType.Outer:
                Kcp.KcpNodelay(kcp, 1, 10, 2, 1);
                Kcp.KcpWndsize(kcp, 256, 256);
                Kcp.KcpSetmtu(kcp, 470);
                Kcp.KcpSetminrto(kcp, 30);
                break;
            }
        }
Beispiel #10
0
        public void HandleConnnect(uint remoteConn)
        {
            if (this.isConnected)
            {
                return;
            }

            this.RemoteConn = remoteConn;

            this.kcp = Kcp.KcpCreate(this.RemoteConn, new IntPtr(this.LocalConn));
            SetOutput();
            Kcp.KcpNodelay(this.kcp, 1, 10, 1, 1);
            Kcp.KcpWndsize(this.kcp, 256, 256);
            Kcp.KcpSetmtu(this.kcp, 470);

            this.isConnected  = true;
            this.lastRecvTime = this.GetService().TimeNow;

            HandleSend();
        }
Beispiel #11
0
        public override void Dispose()
        {
            if (this.IsDisposed)
            {
                return;
            }

            uint localConn  = this.LocalConn;
            uint remoteConn = this.RemoteConn;

            Log.Info($"channel dispose: {this.Id} {localConn} {remoteConn}");

            kChannels.Remove(localConn);
            idLocalRemoteConn.Remove(this.Id);
            // idLocalRemoteConn.TryRemove(this.Id, out ulong _);

            long id = this.Id;

            this.Id = 0;
            this.Service.Remove(id);

            try
            {
                //this.Service.Disconnect(localConn, remoteConn, this.Error, this.RemoteAddress, 3);
            }

            catch (Exception e)
            {
                Log.Error(e);
            }

            if (this.kcp != IntPtr.Zero)
            {
                Kcp.KcpRelease(this.kcp);
                this.kcp = IntPtr.Zero;
            }

            this.socket = null;
        }
Beispiel #12
0
        public void HandleRecv(byte[] date, int offset, int length)
        {
            if (this.IsDisposed)
            {
                return;
            }

            this.IsConnected = true;

            Kcp.KcpInput(this.kcp, date, offset, length);
            this.Service.AddToUpdateNextTime(0, this.Id);

            while (true)
            {
                if (this.IsDisposed)
                {
                    break;
                }
                int n = Kcp.KcpPeeksize(this.kcp);
                if (n < 0)
                {
                    break;
                }
                if (n == 0)
                {
                    this.OnError((int)SocketError.NetworkReset);
                    return;
                }


                if (this.needReadSplitCount > 0)                 // 说明消息分片了
                {
                    byte[] buffer = readMemory.GetBuffer();
                    int    count  = Kcp.KcpRecv(this.kcp, buffer, (int)this.readMemory.Length - this.needReadSplitCount, n);
                    this.needReadSplitCount -= count;
                    if (n != count)
                    {
                        Log.Error($"kchannel read error1: {this.LocalConn} {this.RemoteConn}");
                        this.OnError(ErrorCore.ERR_KcpReadNotSame);
                        return;
                    }

                    if (this.needReadSplitCount < 0)
                    {
                        Log.Error($"kchannel read error2: {this.LocalConn} {this.RemoteConn}");
                        this.OnError(ErrorCore.ERR_KcpSplitError);
                        return;
                    }

                    // 没有读完
                    if (this.needReadSplitCount != 0)
                    {
                        continue;
                    }
                }
                else
                {
                    this.readMemory = this.ms;
                    this.readMemory.SetLength(n);
                    this.readMemory.Seek(0, SeekOrigin.Begin);

                    byte[] buffer = readMemory.GetBuffer();
                    int    count  = Kcp.KcpRecv(this.kcp, buffer, 0, n);
                    if (n != count)
                    {
                        break;
                    }

                    // 判断是不是分片
                    if (n == 8)
                    {
                        int headInt = BitConverter.ToInt32(this.readMemory.GetBuffer(), 0);
                        if (headInt == 0)
                        {
                            this.needReadSplitCount = BitConverter.ToInt32(readMemory.GetBuffer(), 4);
                            if (this.needReadSplitCount <= maxPacketSize)
                            {
                                Log.Error($"kchannel read error3: {this.needReadSplitCount} {this.LocalConn} {this.RemoteConn}");
                                this.OnError(ErrorCore.ERR_KcpSplitCountError);
                                return;
                            }
                            this.readMemory = new MemoryStream(this.needReadSplitCount);
                            this.readMemory.SetLength(this.needReadSplitCount);
                            this.readMemory.Seek(0, SeekOrigin.Begin);
                            continue;
                        }
                    }
                }


                switch (this.Service.ServiceType)
                {
                case ServiceType.Inner:
                    this.readMemory.Seek(Packet.ActorIdLength + Packet.OpcodeLength, SeekOrigin.Begin);
                    break;

                case ServiceType.Outer:
                    this.readMemory.Seek(Packet.OpcodeLength, SeekOrigin.Begin);
                    break;
                }
                this.lastRecvTime = this.Service.TimeNow;
                MemoryStream mem = this.readMemory;
                this.readMemory = null;
                this.OnRead(mem);
            }
        }
Beispiel #13
0
 static KService()
 {
     //Kcp.KcpSetLog(KcpLog);
     Kcp.KcpSetoutput(KcpOutput);
 }
Beispiel #14
0
        public void Update()
        {
            if (this.IsDisposed)
            {
                return;
            }

            uint timeNow = this.GetService().TimeNow;

            // 如果还没连接上,发送连接请求
            if (!this.isConnected)
            {
                // 10秒没连接上则报错
                if (timeNow - this.createTime > 10 * 1000)
                {
                    this.OnError(ErrorCode.ERR_KcpCantConnect);
                    return;
                }

                if (timeNow - this.lastRecvTime < 500)
                {
                    return;
                }

                switch (ChannelType)
                {
                case ChannelType.Accept:
                    this.Accept();
                    break;

                case ChannelType.Connect:
                    this.Connect();
                    break;
                }

                return;
            }

            // 超时断开连接
            //if (timeNow - this.lastRecvTime > 40 * 1000)
            //{
            //	this.OnError(ErrorCode.ERR_KcpChannelTimeout);
            //	return;
            //}

            try
            {
                Kcp.KcpUpdate(this.kcp, timeNow);
            }
            catch (Exception e)
            {
                Log.Error(e);
                this.OnError(ErrorCode.ERR_SocketError);
                return;
            }


            if (this.kcp != IntPtr.Zero)
            {
                uint nextUpdateTime = Kcp.KcpCheck(this.kcp, timeNow);
                this.GetService().AddToUpdateNextTime(nextUpdateTime, this.Id);
            }
        }