コード例 #1
0
        private void ReadAsync()
        {
            try
            {
                while (IsBound)
                {
                    switch (Read())
                    {
                    case ReadState.Void:
                        break;

                    case ReadState.Continue:
                        Thread.Sleep(10);
                        break;

                    case ReadState.Disconnect:
                        return;
                    }
                }
            }
            catch (Exception e)
            {
                // There was in issue reading or executing from the network so disconnect
                // TODO:  Add more logging here and an exception with an inner exception being
                // the exception that was thrown
                BMSLog.LogException(e);
                //Console.WriteLine("CRASH: " + e.Message);
                Disconnect(true);
            }
        }
コード例 #2
0
        /// <summary>
        /// 无限循环在单独的线程上监听来自所有连接客户端的新数据。
        /// readThreadCancel设置为true时,此循环会中断
        ///
        /// Infinite loop listening for new data from all connected clients on a separate thread.
        /// This loop breaks when readThreadCancel is set to true
        /// </summary>
        private void ReadClients()
        {
            //故意无限循环
            // Intentional infinite loop
            while (IsBound && !NetWorker.EndingSession)
            {
                try
                {
                    //如果读取已被标记为取消,则从此循环中断开
                    // If the read has been flagged to be canceled then break from this loop
                    if (readThreadCancel)
                    {
                        return;
                    }

                    //这将遍历所有玩家,因此请确保将锁设置为
                    //防止来自其他线程的任何更改
                    // This will loop through all of the players, so make sure to set the lock to
                    // prevent any changes from other threads
                    lock (Players)
                    {
                        for (int i = 0; i < Players.Count; i++)
                        {
                            //如果读取已被标记为取消,则从此循环中断开
                            // If the read has been flagged to be canceled then break from this loop
                            if (readThreadCancel)
                            {
                                return;
                            }

                            NetworkStream playerStream = null;

                            if (Players[i].IsHost)
                            {
                                continue;
                            }

                            try
                            {
                                lock (Players[i].MutexLock)
                                {
                                    //尝试获取客户端流,如果它仍然可用
                                    // Try to get the client stream if it is still available
                                    playerStream = Players[i].TcpClientHandle.GetStream();
                                }
                            }
                            catch
                            {
                                //无法获取客户端的流,因此强制断开连接
                                //Console.WriteLine("Exception异常:无法为客户端获取流(强制断开连接)“);

                                // Failed to get the stream for the client so forcefully disconnect it
                                //Console.WriteLine("Exception: Failed to get stream for client (Forcefully disconnecting)");
                                Disconnect(Players[i], true);
                                continue;
                            }

                            //如果播放器不再连接,请确保正确断开连接
                            // If the player is no longer connected, then make sure to disconnect it properly
                            if (!Players[i].TcpClientHandle.Connected)
                            {
                                Disconnect(Players[i], false);
                                continue;
                            }

                            //如果有任何数据可用,则只有继续阅读此客户端
                            // Only continue to read for this client if there is any data available for it
                            if (!playerStream.DataAvailable)
                            {
                                continue;
                            }

                            int available = Players[i].TcpClientHandle.Available;

                            try
                            {
                                lock (Players[i].MutexLock)
                                {
                                    // 设置消息ping时间
                                    Players[i].Ping();

                                    // 读取消息
                                    ProtoMsg protoMsg = GetNextBytes(playerStream, available, false);


                                    //客户端已经告诉服务器它正在断开连接
                                    if (protoMsg.protoId == ProtoId.ConnectionClose)
                                    {
                                        //确认连接关闭
                                        protoServer.SendConnectionClose(Players[i].TcpClientHandle);
                                        Disconnect(Players[i], false);
                                        continue;
                                    }

                                    protoServer.OnMessage(protoMsg, Players[i]);
                                }
                            }
                            catch
                            {
                                //播放器发送无效数据,请断开连接
                                Disconnect(Players[i], true);
                            }
                        }
                    }

                    //检查所有挂起的断开连接并清理它们
                    //完成并确定断开连接
                    CleanupDisconnections();

                    //睡眠,这样我们就可以从这个线程释放一些CPU
                    Thread.Sleep(10);
                }
                catch (Exception ex)
                {
                    BMSLog.LogException(ex);
                }
            }
        }
コード例 #3
0
        /// <summary>
        /// This will begin the connection for TCP, this is a thread blocking operation until the connection
        /// is either established or has failed
        /// </summary>
        /// <param name="hostAddress">[127.0.0.1] Ip Address to host from</param>
        /// <param name="port">[15937] Port to allow connections from</param>
        public void Connect(string hostAddress = "0.0.0.0", ushort port = DEFAULT_PORT)
        {
            if (Disposed)
            {
                throw new ObjectDisposedException("TCPServer", "This object has been disposed and can not be used to connect, please use a new TCPServer");
            }

            if (string.IsNullOrEmpty(hostAddress))
            {
                throw new BaseNetworkException("An ip address must be specified to bind to. If you are unsure, you can set to 127.0.0.1");
            }

            // Check to see if this server is being bound to a "loopback" address, if so then bind to any, otherwise bind to specified address
            if (hostAddress == "0.0.0.0" || hostAddress == "localhost")
            {
                ipAddress = IPAddress.Any;
            }
            else
            {
                ipAddress = IPAddress.Parse(hostAddress);
            }

            try
            {
                // Setup and start the base C# TcpListner
                listener = new TcpListener(ipAddress, port);
                //listener.Start();

                Me = new NetworkingPlayer(ServerPlayerCounter++, "0.0.0.0", true, listener, this);
                Me.InstanceGuid = InstanceGuid.ToString();

                // Create the thread that will be listening for clients and start its execution
                //Thread connectionThread = new Thread(new ThreadStart(ListenForConnections));
                //connectionThread.Start();
                //Task.Queue(ListenForConnections);
                listener.Start();
                listener.BeginAcceptTcpClient(ListenForConnections, listener);

                //在成功绑定的结果中执行任何通用初始化
                // Do any generic initialization in result of the successful bind
                OnBindSuccessful();

                //创建将监听来自连接客户端的新数据并开始执行的线程
                // Create the thread that will be listening for new data from connected clients and start its execution
                Task.Queue(ReadClients);

                // 创建将检查播放器超时的线程
                // Create the thread that will check for player timeouts
                Task.Queue(() =>
                {
                    // TODO ZF 关闭检测超时
                    //commonServerLogic.CheckClientTimeout((player) =>
                    //{
                    //    Disconnect(player, true);
                    //    OnPlayerTimeout(player);
                    //    CleanupDisconnections();
                    //});
                });

                //让我知道我连接成功
                //Let myself know I connected successfully
                OnPlayerConnected(Me);
                //将自己设置为连接的客户端
                // Set myself as a connected client
                Me.Connected = true;

                //设置端口
                //Set the port
                SetPort((ushort)((IPEndPoint)listener.LocalEndpoint).Port);
            }
            catch (Exception e)
            {
                BMSLog.LogException(e);
                // Do any generic initialization in result of the binding failure
                OnBindFailure();

                throw new FailedBindingException("Failed to bind to host/port, see inner exception", e);
            }
        }