Esempio n. 1
0
        public ProtoMsg ProtoToData <T>(T protoMsg)
        {
            Type       type = typeof(T);
            IProtoItem item = protoListSender.GetItemByType(type);

            if (item == null)
            {
                Loger.LogTag("Proto", "ProtoToData " + protoMsg + "没找到对应的协议");
                return(default(ProtoMsg));
            }


            MemoryStream stream = new MemoryStream();

            ProtoBuf.Serializer.Serialize <T>(stream, protoMsg);
            stream.Position = 0;

            ProtoMsg msg = new ProtoMsg();

            msg.protoId = item.opcode;
            msg.bytes   = stream.ToArray();

            stream.Dispose();

            return(msg);
        }
        public bool Send(TcpClient client, ProtoMsg frame)
#endif
        {
            if (client == null)
            {
                return(false);
            }

            //确保我们没有写入同一个客户端的竞争条件
            // Make sure that we don't have any race conditions with writing to the same client
            lock (client)
            {
                try
                {
                    //从帧中获取原始字节并发送
                    // Get the raw bytes from the frame and send them
                    byte[] data = frame.GetData();

                    RawWrite(client, data);
                    return(true);
                }
                catch
                {
                    //客户端不再连接或无响应
                    // The client is no longer connected or is unresponsive
                }
            }

            return(false);
        }
Esempio n. 3
0
 /// <summary>
 /// The direct byte send method to the specified client
 /// </summary>
 /// <param name="client">The target client that will receive the frame</param>
 /// <param name="frame">The frame that is to be sent to the specified client</param>
 /// <summary>
 ///直接字节发送方法到指定的客户端
 /// </ summary>
 /// <param name =“client”>将接收帧的目标客户端</ param>
 /// <param name =“frame”>要发送到指定客户端的帧</ param>
 public virtual void Send(ProtoMsg frame)
 {
     //确保我们没有写入同一个客户端的竞争条件
     // Make sure that we don't have any race conditions with writing to the same client
     lock (client)
     {
         //从帧中获取原始字节并发送
         // Get the raw bytes from the frame and send them
         byte[] data = frame.GetData();
         RawWrite(data);
     }
 }
Esempio n. 4
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>
        protected ReadState Read()
        {
            if (disconnectedSelf)
            {
                return(ReadState.Disconnect);
            }

            NetworkStream stream = client.GetStream();

            if (stream == null) //Some reason the stream is null! //某些原因流为空!
            {
                return(ReadState.Continue);
            }

            //如果流不再可读,则断开连接
            // If the stream no longer can read then disconnect
            if (!stream.CanRead)
            {
                Disconnect(true);
                return(ReadState.Disconnect);
            }

            //如果没有可用的数据,则通过休眠线程释放CPU
            // If there isn't any data available, then free up the CPU by sleeping the thread
            if (!stream.DataAvailable)
            {
                return(ReadState.Continue);
            }

            int available = client.Available;

            if (available == 0)
            {
                return(ReadState.Continue);
            }


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

            //客户端已经告诉服务器它正在断开连接
            if (protoMsg.protoId == ProtoId.ConnectionClose)
            {
                Disconnect(true);
                return(ReadState.Disconnect);
            }

            proto.OnMessage(protoMsg, server);

            return(ReadState.Void);
        }
Esempio n. 5
0
        public void SendMessage <T>(T protoMsg, TcpClient client)
        {
            Type       type = typeof(T);
            IProtoItem item = protoListSender.GetItemByType(type);

            if (item == null)
            {
                Loger.LogTag("Proto", "-> " + protoMsg + "没找到对应的协议");
                return;
            }

            Loger.LogTag("Proto", "-> " + item);

            ProtoMsg msg = ProtoToData <T>(protoMsg);

            baseTcp.SendToPlayer(client, msg);
        }
Esempio n. 6
0
        /// <summary>
        /// 接收消息
        /// </summary>
        public void OnMessage(ProtoMsg msg, NetworkingPlayer player)
        {
            IProtoItem item = protoListListener.GetItemByOpcode(msg.protoId);

            if (item != null)
            {
                Loger.LogTag("Proto", "<= " + item);
            }
            else
            {
                Loger.LogTag("Proto", "<= " + msg.protoId + "没找到对应的协议");
            }

            if (item != null && item.hasListen)
            {
                item.Handle(msg.bytes, player);
            }
        }
        /// <summary>
        /// Goes through all of the currently connected players and send them the frame
        /// </summary>
        /// <param name="frame">The frame to send to all of the connected players</param>
        /// <summary>
        ///通过所有当前连接的玩家,并将其发送给他们
        /// </ summary>
        /// <param name =“frame”>发送给所有连接的播放器的帧</ param>
        public void SendAll(ProtoMsg frame, Receivers receivers = Receivers.All, NetworkingPlayer skipPlayer = null)
        {
            lock (Players)
            {
                foreach (NetworkingPlayer player in Players)
                {
                    if (!commonServerLogic.PlayerIsReceiver(player, Me, receivers, skipPlayer))
                    {
                        continue;
                    }

                    try
                    {
                        Send(player.TcpClientHandle, frame);
                    }
                    catch
                    {
                        Disconnect(player, true);
                    }
                }
            }
        }
Esempio n. 8
0
        /// <summary>
        /// 读取当前的客户端流,并从中取出下一组数据
        /// </summary>
        /// <param name =“playerClient”>要从</ param>中读取的客户端
        /// <param name =“usingMask”>更改算法以查找要使用的字节中的掩码</ param>
        /// <returns>为这个帧读取的字节</ returns>
        protected ProtoMsg GetNextBytes(NetworkStream stream, int available, bool usingMask)
        {
            ProtoMsg msg = new ProtoMsg();

            //将缓冲区设置为现在有可用字节的长度
            byte[] bytes = new byte[9];

            // 包头结构: 前四个字节表示数据包长度, 随后两字节表示消息类型
            // int32 :总长度, 包含包头及包尾长度
            // int16 :消息类型
            stream.Read(bytes, 0, 6);
            int length = BitConverter.ToInt32(bytes, 0);
            int propId = BitConverter.ToInt16(bytes, 4);

            length -= 6 - 9;

            // 包体
            byte[] body = null;
            if (length > 0)
            {
                body = new byte[length];
                stream.Read(body, 6, length);
            }


            // 包尾 包尾结构: 1个字节表示包尾类型, 随后8个字符表示类型参数
            stream.Read(bytes, 6 + length, 9);
            byte fromType = bytes[0];
            long fromId   = BitConverter.ToInt64(bytes, 1);

            msg.protoId  = propId;
            msg.bytes    = body;
            msg.fromType = fromType;
            msg.fromId   = fromId;

            return(msg);
        }
Esempio n. 9
0
 public virtual void SendToPlayer(TcpClient client, ProtoMsg frame)
 {
 }
Esempio n. 10
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);
                }
            }
        }
Esempio n. 11
0
 public override void SendToPlayer(TcpClient client, ProtoMsg frame)
 {
     Send(client, frame);
 }
Esempio n. 12
0
        /// <summary>
        /// The direct byte send method to the specified client
        /// </summary>
        /// <param name="client">The target client that will receive the frame</param>
        /// <param name="frame">The frame that is to be sent to the specified client</param>
        /// <summary>
        ///直接字节发送方法到指定的客户端
        /// </ summary>
        /// <param name =“client”>将接收帧的目标客户端</ param>
        /// <param name =“frame”>要发送到指定客户端的帧</ param>
#if WINDOWS_UWP
        public bool Send(StreamSocket client, ProtoMsg frame)