Пример #1
0
        /*
         *  判断当前连接是否建立
         */
        public bool IsConnected()
        {
            if (null == socket_)
            {
                return(false);
            }

            // 通过尝试获取服务器地址,判断连接是否断开
            bool res = true;

            try
            {
                if (_remoteEndPoint == null)
                {
                    res = false;
                }
            }
            catch (SystemException)
            {
                res = false;
            }

            // 连接意外断开后,调用用户回调函数
            if (!res && connected_before_)
            {
                SuperDebug.Warning(DebugPrefix.Network, "connect to " + host_ + ":" + port_ + " break down.");
                connected_before_ = false;
                if (null != disconnect_callback_)
                {
                    disconnect_callback_();
                }
            }

            return(res);
        }
Пример #2
0
        public bool SetData <T>(T data, PacketSession session) where T : IMessage
        {
            try
            {
                _content = data;
                _session = session;
                _cmdId   = (ushort)session.CmdId;

                _bodyMem.Position = 0;
                _bodyMem.SetLength(0);

                _bodyMem.Write(NetUtils.UshortToBigEndian(_cmdId), 0, NetDefine.CMD_BYTES);
                _bodyMem.Seek(NetDefine.BODY_HEAD_LEN, SeekOrigin.Begin);

                session.WriteTo(_bodyMem);
                long sessionPos = _bodyMem.Position;

                data.WriteTo(_bodyMem);
                long contentPos = _bodyMem.Position;

                _bodyMem.Seek(NetDefine.CMD_BYTES, SeekOrigin.Begin);

                _bodyMem.Write(NetUtils.UshortToBigEndian((ushort)(sessionPos - NetDefine.BODY_HEAD_LEN)), 0, NetDefine.SESSION_LEN_BYTES);
                _bodyMem.Write(NetUtils.UintToBigEndian((uint)(contentPos - sessionPos)), 0, NetDefine.CONTENT_LEN_BYTES);

                //OutputBytes("true data:", body_.GetBuffer(), body_.Length);
            }
            catch (System.Exception e)
            {
                SuperDebug.Warning(DebugPrefix.Network, "Serialize " + typeof(T).ToString() + " meet exception " + e);
                return(false);
            }

            return(true);
        }
Пример #3
0
        private void Reconnect()
        {
            _reconnectTimes += 1;
            _timer           = 0;
            _status          = Status.WaitingConnect;

            SuperDebug.Warning(DebugPrefix.Network, "===========Reconnect");

            NetworkManager.Instance.LoginGameServer();
        }
Пример #4
0
        void ConsumePacket()
        {
            NetPacket packet = _client.Recv(0);

            if (packet != null)
            {
                DispatchPacket(packet);
            }
            else
            {
                /* 检查网络连接状态 */
                if (CheckReachabilityChange())
                {
                    SuperDebug.Warning(DebugPrefix.Network, "=========== internetReachability changed to " + netReach);
                    if (_client.IsConnected())
                    {
                        SuperDebug.Warning(DebugPrefix.Network, "=========== disconnect by MonoClientPacketConsumer");
                        _client.Disconnect();
                    }
                }

                //	disconnected check
                bool isConnected = _client.IsConnected();
                if (!isConnected && _lastIsConnected &&
                    NetworkManager.Instance.onUnexpectedDisconnect != null)
                {
                    NetworkManager.Instance.onUnexpectedDisconnect();
                }
                _lastIsConnected = isConnected;

                if (!isConnected)
                {
                    if (_status == Status.Normal)
                    {
                        _status = Status.WaitingConnect;
                        Reconnect();
                    }
                    else if (_status == Status.WaitingConnect)
                    {
                        _timer += Time.deltaTime;
                        if (_timer > RECONNECT_INTERVAL)
                        {
                            ShowLoadingWheel();
                            Reconnect();
                        }
                    }
                    else if (_status == Status.RepeatLogin)
                    {
                        TryShowErrorDialog();
                    }
                }
            }

            return;
        }
Пример #5
0
        public Type GetTypeByCmdID(ushort cmdID)
        {
            Type resType;

            if (!_cmdIDMap.TryGetValue(cmdID, out resType))
            {
                SuperDebug.Warning(DebugPrefix.Network, "undefined cmdID=" + cmdID);
            }

            return(resType);
        }
Пример #6
0
        public ushort GetCmdIDByType(Type type)
        {
            ushort resCmdID;

            if (!_typeMap.TryGetValue(type, out resCmdID))
            {
                SuperDebug.Warning(DebugPrefix.Network, "undefined type=" + type);
            }

            return(resCmdID);
        }
Пример #7
0
        /*
         *  设置心跳包
         */
        public bool SetKeepalive(int time_ms, NetPacket packet)
        {
            if (time_ms <= 0 || null == packet)
            {
                SuperDebug.Warning(DebugPrefix.Network, "time_ms<=0 or packet==null");
                return(false);
            }

            keepalive_time_ms_ = time_ms;
            keepalive_packet_  = packet;
            return(true);
        }
Пример #8
0
        /*
         *  启动接受数据的线程
         */
        private bool StartClientThread()
        {
            if (IsClientThreadRun())
            {
                SuperDebug.Warning(DebugPrefix.Network, "recv thread is already running now, can not restart.");
                return(false);
            }
            client_producer_thread_ = new Thread(ClientProducerThreadHandler);
            client_producer_thread_.Start();

            return(true);
        }
Пример #9
0
        /*
         *  循环读取数据的线程, 逐个处理包
         *  目前读取在主线程中,而不在网络线程中
         */
        private void ClientConsumerThreadHandler()
        {
            SuperDebug.Log(DebugPrefix.Network, "clientConsumer thread start.");
            while (IsConnected() || 0 < recv_queue_.Count)
            {
                // 等待的毫秒数,为 Timeout.Infinite,表示无限期等待。
                NetPacket packet = Recv(Timeout.Infinite);

                if (packet != null)
                {
                    SuperDebug.Log(DebugPrefix.Network, "clientConsumer recv: CmdId=" + packet.GetCmdId());
                    doCmd_callback_(packet);
                }
                else
                {
                    SuperDebug.Warning(DebugPrefix.Network, "packet = null in clientConsumerThreadHandler");
                }
            }

            SuperDebug.Log(DebugPrefix.Network, "clientConsumer thread stop.");
        }
Пример #10
0
        /*
         *  同步方式发送一个标准消息包到服务器
         */
        public bool Send(NetPacket packet)
        {
            if (!IsConnected())
            {
                SuperDebug.Warning(DebugPrefix.Network, "client is not connected, can not send now.");
                return(false);
            }

            // 序列化
            MemoryStream ms = new MemoryStream();

            packet.Serialize(ref ms);

            // 发送
            /* fix: ObjectDisposedException: The object was used after being disposed. */
            // 因为另一个线程会close掉socket,在close的同时send,就会导致上面的报错,加了Try-Catch */
            try
            {
                SocketError error    = new SocketError();
                int         send_len = socket_.Send(ms.GetBuffer(), 0, (int)ms.Length, SocketFlags.None, out error);
                if (error != SocketError.Success)
                {
                    SuperDebug.Warning(DebugPrefix.Network, "send failed: " + error);
                    return(false);
                }
                if (send_len != ms.Length)
                {                //???does this happen?
                    SuperDebug.Warning(DebugPrefix.Network, "packet_len=" + ms.Length + ", but only send " + send_len);
                    return(false);
                }
            }
            catch (Exception e)
            {
                SuperDebug.Warning(DebugPrefix.Network, "exception e=" + e.ToString());
                return(false);
            }

            return(true);
        }
Пример #11
0
        /*
         *  建立连接
         */
        public bool Connect(string host, ushort port, int timeout_ms = 2000)         //以毫秒为单位
        {
            try
            {
                // 检查是否已经建立连接
                if (IsConnected())
                {
                    SuperDebug.Warning(DebugPrefix.Network, "client is already connected to " + host_ + ":" + port_ + ", can not connect to other server now.");
                    return(false);
                }

                // 赋值
                host_       = host;
                port_       = port;
                timeout_ms_ = timeout_ms;

                // 根据host获取ip列表
                IPAddress[] ip_list = Dns.GetHostAddresses(host_);
                if (0 == ip_list.Length)
                {
                    SuperDebug.Warning(DebugPrefix.Network, "can not get any ip address from host " + host_);
                    return(false);
                }

                // 尝试连接每个ip
                socket_         = null;
                _remoteEndPoint = null;
                for (int idx = 0; idx < ip_list.Length; idx++)
                {
                    IPAddress ip_tmp = GetIPAddress(ip_list[idx]);

                    SuperDebug.Log(DebugPrefix.Network, "try to connect to " + ip_tmp);
                    IPEndPoint ipe        = new IPEndPoint(ip_tmp, port_);
                    Socket     socket_tmp = new Socket(ipe.AddressFamily, SocketType.Stream, ProtocolType.Tcp);

                    // 初始化socket属性
                    socket_tmp.NoDelay           = true;
                    socket_tmp.Blocking          = true;
                    socket_tmp.SendTimeout       = timeout_ms_;
                    socket_tmp.ReceiveTimeout    = timeout_ms_;
                    socket_tmp.ReceiveBufferSize = ClientDefine.g_recv_buf_size * 2;

                    // 连接
                    timeout_event_.Reset();
                    socket_tmp.BeginConnect(ip_tmp, port_, new AsyncCallback(ConnectCallback), socket_tmp);

                    // 超时等待连接建立
                    timeout_event_.WaitOne(timeout_ms, false);

                    // 检验连接是否成功
                    if (socket_tmp.Connected)
                    {
                        socket_         = socket_tmp;
                        _remoteEndPoint = ipe;
                        SuperDebug.Log(DebugPrefix.Network, "socket_.ReceiveBufferSize= " + socket_.ReceiveBufferSize);

                        break;
                    }
                    else
                    {
                        SuperDebug.Log(DebugPrefix.Network, "connect to " + ip_tmp + " timeout.");
                        continue;
                    }
                }

                // 检查是否成功连接
                if (null == socket_)
                {
                    SuperDebug.Warning(DebugPrefix.Network, "connect to " + host_ + ":" + port_ + " failed.");
                    return(false);
                }
                else
                {
                    SuperDebug.Log(DebugPrefix.Network, "connect to " + host_ + ":" + port_ + " succ.");
                    SuperDebug.Log(DebugPrefix.Network, "_remoteEndPoint= " + _remoteEndPoint);
                }

                // 启动工作线程
                StartClientThread();

                //
                connected_before_ = true;
            }
            catch (System.Exception e)
            {
                SuperDebug.Error(DebugPrefix.Network, "connect to " + host + ":" + port + " meet exception " + e.ToString());
                return(false);
            }

            return(true);
        }
Пример #12
0
        /*
         *  同步方式接受多个消息
         *      如果当前有可读消息,则立刻返回,否则超时等待设置的时间
         */
        private List <NetPacket> RecvPacketList()
        {
            // 检查连接状态
            if (!IsConnected())
            {
                SuperDebug.Warning(DebugPrefix.Network, "client is not connected, can not recv now.");
                return(null);
            }

            // 开始接受数据
            List <NetPacket> list = new List <NetPacket>();

            try
            {
                // 接受到缓存
                byte[]      recv_buf = new byte[ClientDefine.g_recv_buf_size - left_buf_len_];
                SocketError error    = new SocketError();
                int         recv_len = socket_.Receive(recv_buf, 0, recv_buf.Length, SocketFlags.None, out error);

                // 接受超时立刻返回
                if (error == SocketError.TimedOut ||
                    error == SocketError.WouldBlock ||
                    error == SocketError.IOPending)
                {
                    return(list);
                }

                // 如果接受数据长度为0,则表示连接出现异常,需要立刻使用回调函数通知使用方
                if (error != SocketError.Success || 0 == recv_len)
                {
                    SuperDebug.Warning(DebugPrefix.Network, "recv failed with recv_len=" + recv_len + ", error=" + error);
                    socket_.Close();
                    socket_ = null;
                    return(list);
                }

                // 合并上次剩余、本次收到的数据
                byte[] total_buf = new byte[ClientDefine.g_recv_buf_size];
                Array.Copy(left_buf_, 0, total_buf, 0, left_buf_len_);
                Array.Copy(recv_buf, 0, total_buf, left_buf_len_, recv_len);
                int total_len = recv_len + left_buf_len_;
                left_buf_len_ = 0;

                // 开始处理
                int used = 0;

                // 一次可能recv多个packet,循环反序列化每个packet,并加入list
                while (used < total_len)
                {
                    //缓存之前的有效数据
                    if (_tempPacket == null)
                    {
                        _tempPacket = new NetPacket();
                    }

                    PacketStatus packet_status = _tempPacket.Deserialize(ref total_buf, ref used, total_len);

                    if (PacketStatus.PACKET_CORRECT != packet_status)
                    {
                        // 存储残缺的数据
                        if (PacketStatus.PACKET_NOT_COMPLETE == packet_status)
                        {
                            left_buf_len_ = total_len - used;
                            Array.Copy(total_buf, used, left_buf_, 0, left_buf_len_);
                        }
                        else
                        {
                            SuperDebug.Warning(DebugPrefix.Network, "deserialize packet failed. " + packet_status);
                        }

                        break;
                    }
                    else
                    {
                        list.Add(_tempPacket);
                        _tempPacket = null;
                    }
                }
            }
            catch (SystemException e)
            {
                if (IsConnected())
                {
                    SuperDebug.Error(DebugPrefix.Network, "recv failed: " + e);
                }
            }
            return(list);
        }