Esempio n. 1
0
        // Should validate the handshake response from the server
        private void ReceiveAsync_Completed(object sender, SocketAsyncEventArgs e)
        {
            if (e.BytesTransferred > 0 && e.SocketError == SocketError.Success)
            {
                int          bytesAlreadyProcessed = 0; // Count of the total freshly transferred bytes processed so far
                ReceiveToken token = (ReceiveToken)e.UserToken;
                if (!headerExchanged)
                {
                    byte[] header = HandleHttpHeader(e, ref bytesAlreadyProcessed);
                    token = (ReceiveToken)e.UserToken;
                    if (header == null)
                    {
                        DoRead(e);
                        return;
                    }
                    else if (Websockets.ValidateResponseHeader(headerHash, header))
                    {
                        headerExchanged       = true;
                        token.maxAllowedBytes = int.MaxValue;
                        e.UserToken           = token;

                        // Ping the server to finalize the player's connection
                        Send(Text.CreateFromString(Time.Timestep, InstanceGuid.ToString(), true, Receivers.Server,
                                                   MessageGroupIds.NETWORK_ID_REQUEST, true));
                    }
                    else
                    {
                        // Improper header, so a disconnect is required
                        Disconnect(true);
                        return;
                    }
                }

                while (bytesAlreadyProcessed < e.BytesTransferred)
                {
                    byte[] data = HandleData(e, true, ref bytesAlreadyProcessed);
                    if (data == null)
                    {
                        break;
                    }

                    FrameStream frame = Factory.DecodeMessage(data, false, MessageGroupIds.TCP_FIND_GROUP_ID, Server);

                    FireRead(frame, Server);
                }

                DoRead(e);
            }
            else
            {
                Disconnect(true);
            }
        }
        /// <summary>
        /// Infinite loop listening for new data from all connected clients on a separate thread.
        /// This loop breaks when readThreadCancel is set to true
        /// </summary>
        /// <summary>
        ///无限循环在单独的线程上监听来自所有连接客户端的新数据。
        ///当readThreadCancel设置为true时,此循环中断
        /// </ summary>
        private void ReadNetwork()
        {
            IPEndPoint groupEP          = new IPEndPoint(IPAddress.Any, 0);
            string     incomingEndpoint = string.Empty;

            try
            {
                BMSByte packet = null;
                // Intentional infinite loop
                while (IsBound)
                {
                    //如果读取已被标记为取消,则从此循环中断开
                    // If the read has been flagged to be canceled then break from this loop
                    if (readThreadCancel)
                    {
                        return;
                    }

                    try
                    {
                        // Read a packet from the network
                        packet = Client.Receive(ref groupEP, ref incomingEndpoint);

                        if (PacketLossSimulation > 0.0f && new Random().NextDouble() <= PacketLossSimulation)
                        {
                            // Skip this message
                            continue;
                        }

                        BandwidthIn += (ulong)packet.Size;
                    }
                    catch (SocketException /*ex*/)
                    {
                        // This is a common exception when we exit the blocking call
                        //Logging.BMSLog.LogException(ex);
                        Disconnect(true);
                    }

                    // Check to make sure a message was received
                    if (packet == null || packet.Size <= 0)
                    {
                        continue;
                    }

                    // This message was not from the server
                    if (groupEP.Address != Server.IPEndPointHandle.Address &&
                        groupEP.Port != Server.IPEndPointHandle.Port)
                    {
                        if (packet.Size == 1 && (packet[0] == SERVER_BROADCAST_CODE || packet[1] == CLIENT_BROADCAST_CODE))
                        {
                        }
                        else if (packet.Size.Between(2, 4) && packet[0] == BROADCAST_LISTING_REQUEST_1 && packet[1] == BROADCAST_LISTING_REQUEST_2 && packet[2] == BROADCAST_LISTING_REQUEST_3)
                        {
                            //这可能是一个本地列表请求,所以用客户端标志字节进行响应
                            // This may be a local listing request so respond with the client flag byte
                            Client.Send(new byte[] { CLIENT_BROADCAST_CODE }, 1, groupEP);
                        }

                        continue;
                    }

                    // Check to see if the headers have been exchanged
                    if (!headerExchanged)
                    {
                        if (Websockets.ValidateResponseHeader(headerHash, packet.CompressBytes()))
                        {
                            headerExchanged = true;

                            // TODO:  When getting the user id, it should also get the server time
                            // by using the current time in the payload and getting it back along with server time

                            // Ping the server to finalize the player's connection
                            Send(Text.CreateFromString(Time.Timestep, InstanceGuid.ToString(), false, Receivers.Server, MessageGroupIds.NETWORK_ID_REQUEST, false), true);
                        }
                        else if (packet.Size != 1 || packet[0] != 0)
                        {
                            Disconnect(true);
                            break;
                        }
                        else
                        {
                            continue;
                        }
                    }
                    else
                    {
                        if (packet.Size < 17)
                        {
                            continue;
                        }

                        // 格式的字节数据到一个udppacket结构
                        // Format the byte data into a UDPPacket struct
                        UDPPacket formattedPacket = TranscodePacket(Server, packet);

                        // Check to see if this is a confirmation packet, which is just
                        // a packet to say that the reliable packet has been read
                        if (formattedPacket.isConfirmation)
                        {
                            if (formattedPacket.groupId == MessageGroupIds.DISCONNECT)
                            {
                                CloseConnection();
                                return;
                            }

                            OnMessageConfirmed(server, formattedPacket);
                            continue;
                        }

                        //将数据包添加到管理器,以便可以在完成时跟踪和执行
                        // Add the packet to the manager so that it can be tracked and executed on complete
                        packetManager.AddPacket(formattedPacket, PacketSequenceComplete, this);
                    }
                }
            }
            catch (Exception ex)
            {
                Logging.BMSLog.LogException(ex);
                Disconnect(true);
            }
        }