/// <summary> /// Instantiate an instance of Player /// </summary> /// <returns> /// A local instance of PlayerBehavior /// </returns> /// <param name="index">The index of the Player prefab in the NetworkManager to Instantiate</param> /// <param name="position">Optional parameter which defines the position of the created GameObject</param> /// <param name="rotation">Optional parameter which defines the rotation of the created GameObject</param> /// <param name="sendTransform">Optional Parameter to send transform data to other connected clients on Instantiation</param> public PlayerBehavior InstantiatePlayer(int index = 0, Vector3?position = null, Quaternion?rotation = null, bool sendTransform = true) { if (PlayerNetworkObject.Length <= index) { Debug.Log("Prefab(s) missing for: Player. Add them at the NetworkManager prefab."); return(null); } var go = Instantiate(PlayerNetworkObject[index]); var netBehavior = go.GetComponent <PlayerBehavior>(); NetworkObject obj = null; if (!sendTransform && position == null && rotation == null) { obj = netBehavior.CreateNetworkObject(Networker, index); } else { metadata.Clear(); if (position == null && rotation == null) { byte transformFlags = 0x1 | 0x2; ObjectMapper.Instance.MapBytes(metadata, transformFlags); ObjectMapper.Instance.MapBytes(metadata, go.transform.position, go.transform.rotation); } else { byte transformFlags = 0x0; transformFlags |= (byte)(position != null ? 0x1 : 0x0); transformFlags |= (byte)(rotation != null ? 0x2 : 0x0); ObjectMapper.Instance.MapBytes(metadata, transformFlags); if (position != null) { ObjectMapper.Instance.MapBytes(metadata, position.Value); } if (rotation != null) { ObjectMapper.Instance.MapBytes(metadata, rotation.Value); } } obj = netBehavior.CreateNetworkObject(Networker, index, metadata.CompressBytes()); } go.GetComponent <PlayerBehavior>().networkObject = (PlayerNetworkObject)obj; FinalizeInitialization(go, netBehavior, obj, position, rotation, sendTransform); return(netBehavior); }
public BulletBehavior InstantiateBullet(int index = 0, Vector3?position = null, Quaternion?rotation = null, bool sendTransform = true) { var go = Instantiate(BulletNetworkObject[index]); var netBehavior = go.GetComponent <BulletBehavior>(); NetworkObject obj = null; if (!sendTransform && position == null && rotation == null) { obj = netBehavior.CreateNetworkObject(Networker, index); } else { metadata.Clear(); if (position == null && rotation == null) { metadata.Clear(); byte transformFlags = 0x1 | 0x2; ObjectMapper.Instance.MapBytes(metadata, transformFlags); ObjectMapper.Instance.MapBytes(metadata, go.transform.position, go.transform.rotation); } else { byte transformFlags = 0x0; transformFlags |= (byte)(position != null ? 0x1 : 0x0); transformFlags |= (byte)(rotation != null ? 0x2 : 0x0); ObjectMapper.Instance.MapBytes(metadata, transformFlags); if (position != null) { ObjectMapper.Instance.MapBytes(metadata, position.Value); } if (rotation != null) { ObjectMapper.Instance.MapBytes(metadata, rotation.Value); } } obj = netBehavior.CreateNetworkObject(Networker, index, metadata.CompressBytes()); } go.GetComponent <BulletBehavior>().networkObject = (BulletNetworkObject)obj; FinalizeInitialization(go, netBehavior, obj, position, rotation, sendTransform); return(netBehavior); }
private void SetupClient(BMSByte packet, string incomingEndpoint, IPEndPoint groupEP) { // Check for a local listing request if (packet.Size.Between(2, 4) && packet[0] == BROADCAST_LISTING_REQUEST_1 && packet[1] == BROADCAST_LISTING_REQUEST_2 && packet[2] == BROADCAST_LISTING_REQUEST_3) { // Don't reply if the server is not currently accepting connections if (!AcceptingConnections) { return; } // This may be a local listing request so respond with the server flag byte Client.Send(new byte[] { SERVER_BROADCAST_CODE }, 1, groupEP); return; } if (Players.Count == MaxConnections) { // Tell the client why they are being disconnected Send(Error.CreateErrorMessage(Time.Timestep, "Max Players Reached On Server", false, MessageGroupIds.MAX_CONNECTIONS, true)); // Send the close connection frame to the client Send(new ConnectionClose(Time.Timestep, false, Receivers.Target, MessageGroupIds.DISCONNECT, false)); return; } else if (!AcceptingConnections) { // Tell the client why they are being disconnected Send(Error.CreateErrorMessage(Time.Timestep, "The server is busy and not accepting connections", false, MessageGroupIds.MAX_CONNECTIONS, true)); // Send the close connection frame to the client Send(new ConnectionClose(Time.Timestep, false, Receivers.Target, MessageGroupIds.DISCONNECT, false)); return; } // Validate that the connection headers are properly formatted byte[] response = Websockets.ValidateConnectionHeader(packet.CompressBytes()); // The response will be null if the header sent is invalid, if so then disconnect client as they are sending invalid headers if (response == null) { return; } UDPNetworkingPlayer player = new UDPNetworkingPlayer(ServerPlayerCounter++, incomingEndpoint, false, groupEP, this); // If all is in order then send the validated response to the client Client.Send(response, response.Length, groupEP); OnPlayerConnected(player); udpPlayers.Add(incomingEndpoint, player); // The player has successfully connected player.Connected = true; }
/// <summary> /// This constructor will take a payload and create a new frame with the appropriate structure /// </summary> /// <param name="timestep">The timestep that this frame is created within</param> /// <param name="useMask">If set to <c>true</c> a mask will be used to encode the payload.</param> /// <param name="payload">The new frame initial data data</param> /// <param name="routerId">A byte that can be used to route data within a user program</param> public FrameStream(ulong timestep, bool useMask, BMSByte payload, Receivers receivers, int groupId, bool isStream, byte routerId = 0) { if (payload == null) { // TODO: Throw frame exception throw new BaseNetworkException("The payload for the frame is not allowed to be null, otherwise use other constructor"); } CreateFrame(useMask, timestep, payload.CompressBytes(), receivers, groupId, routerId, isStream); }
protected override BMSByte SerializeDirtyFields() { if (firstFrame) { BMSByte bmsByte = new BMSByte(); bmsByte = WritePayload(bmsByte); PTK.ArenaObservable.PlayerData _playerData = new PTK.ArenaObservable.PlayerData(); _playerData.BMSData = Convert.ToBase64String(bmsByte.CompressBytes()); _playerData.UID = PTK.Ansuz.Instance.UID; _playerData.RequestID = (int)PTK.AnsuzRequestID.CreatePlayer; PTK.ArenaObservable.PlayerData[] objs = { _playerData }; string json = _playerData.ToJson <PTK.ArenaObservable.PlayerData>(objs, false); PTK.Ansuz.Instance.PublishToTopic("arena/playerData/all", json, 0); firstFrame = false; } dirtyFieldsData.Clear(); dirtyFieldsData.Append(_dirtyFields); if ((0x1 & _dirtyFields[0]) != 0) { UnityObjectMapper.Instance.MapBytes(dirtyFieldsData, _position); } if ((0x2 & _dirtyFields[0]) != 0) { UnityObjectMapper.Instance.MapBytes(dirtyFieldsData, _rotation); } if ((0x4 & _dirtyFields[0]) != 0) { UnityObjectMapper.Instance.MapBytes(dirtyFieldsData, _spineRotation); } if ((0x8 & _dirtyFields[0]) != 0) { UnityObjectMapper.Instance.MapBytes(dirtyFieldsData, _vertical); } if ((0x10 & _dirtyFields[0]) != 0) { UnityObjectMapper.Instance.MapBytes(dirtyFieldsData, _horizontal); } if ((0x20 & _dirtyFields[0]) != 0) { UnityObjectMapper.Instance.MapBytes(dirtyFieldsData, _isMoving); } // Reset all the dirty fields for (int i = 0; i < _dirtyFields.Length; i++) { _dirtyFields[i] = 0; } return(dirtyFieldsData); }
public virtual NetworkBehavior InstantiateNetworkBehavior(int pCreateCode = -1, IRPCSerializable pBehaviorData = null, Vector3?pPosition = null, Quaternion?pRotation = null, bool pSendTransform = true) { GameObject prefab = _networkBehaviorListSO.behaviorList.GetByCreateCode(pCreateCode); if (prefab == null) { return(null); } var go = Instantiate(prefab); var netBehavior = go.GetComponent <NetworkBehavior>(); NetworkObject obj = null; if (!pSendTransform && pPosition == null && pRotation == null) { obj = netBehavior.CreateNetworkObject(_networker, pCreateCode); } else { _tmpMetadata.Clear(); if (pPosition == null && pRotation == null) { byte transformFlags = 0x1 | 0x2; ObjectMapper.Instance.MapBytes(_tmpMetadata, transformFlags); ObjectMapper.Instance.MapBytes(_tmpMetadata, go.transform.position, go.transform.rotation); } else { byte transformFlags = 0x0; transformFlags |= (byte)(pPosition != null ? 0x1 : 0x0); transformFlags |= (byte)(pRotation != null ? 0x2 : 0x0); ObjectMapper.Instance.MapBytes(_tmpMetadata, transformFlags); if (pPosition != null) { ObjectMapper.Instance.MapBytes(_tmpMetadata, pPosition.Value); } if (pRotation != null) { ObjectMapper.Instance.MapBytes(_tmpMetadata, pRotation.Value); } } obj = netBehavior.CreateNetworkObject(_networker, pCreateCode, _tmpMetadata.CompressBytes()); } SetINetworkSceneObject(netBehavior, obj); SetIRPCSerializable(netBehavior, pBehaviorData); FinalizeInitialization(go, netBehavior, obj, pPosition, pRotation, pSendTransform); return(netBehavior); }
public void AppendBytesRemoveStart3() { byte[] data = new byte[] { 1, 8, 9, 34, 255, 0, 33, 66, 100, 128 }; var cache = new BMSByte(); cache.Append(data); cache.RemoveStart(3); byte[] response = cache.CompressBytes(); for (int i = 3; i < data.Length; i++) { Assert.AreEqual(data[i], response[i - 3]); } }
public void AppendBytesAndCompressBytes() { byte[] data = new byte[] { 1, 8, 9, 34, 255, 0, 33, 66, 100, 128 }; var cache = new BMSByte(); cache.Append(data); byte[] response = cache.CompressBytes(); Assert.AreEqual(data.Length, response.Length); for (int i = 0; i < data.Length; i++) { Assert.AreEqual(data[i], response[i]); } }
private static void ReadBinaryMessage(NetworkingPlayer player, Binary frame, NetWorker sender) { BMSByte data = new BMSByte(); data.Clone(frame.GetData()); if (data[0] == 212) { data.MoveStartIndex(1); System.IO.File.WriteAllBytes("testRead.txt", data.CompressBytes()); Console.WriteLine("Wrote file from network"); } }
/// <summary> /// Gets the raw data for this frame /// </summary> /// <returns>The raw byte data prepared by this frame</returns> public byte[] GetData(bool makeReliable = false, NetworkingPlayer player = null) { if (makeReliable) { MakeReliable(player); reliableCloneData.Clone(StreamData); reliableCloneData.InsertRange(StreamData.Size - (sizeof(ulong) * 2), BitConverter.GetBytes(UniqueReliableId)); return(reliableCloneData.CompressBytes()); } return(StreamData.CompressBytes()); }
private void PacketSequenceComplete(BMSByte data, int groupId, byte receivers) { // Pull the frame from the sent message FrameStream frame = Factory.DecodeMessage(data.CompressBytes(), false, groupId, Server, receivers); if (frame is ConnectionClose) { CloseConnection(); return; } // Send an event off that a packet has been read OnMessageReceived(Server, frame); }
private void PacketSequenceComplete(BMSByte data, int groupId, byte receivers, bool isReliable) { // Pull the frame from the sent message FrameStream frame = Factory.DecodeMessage(data.CompressBytes(), false, groupId, ServerPlayer, receivers); if (isReliable) { ProcessCompletedReliableFrame(frame); } else { FireRead(frame, ServerPlayer); } }
protected UDPPacket TranscodePacket(NetworkingPlayer sender, BMSByte packet) { byte meta = PullPacketMetadata(packet); // If the last byte says it is reliable bool reliable = (0x1 & meta) != 0; // If the last byte says that it is the last packet for this group bool endPacket = (0x2 & meta) != 0; // If the last byte says that it is a conformation packet bool confirmationPacket = (0x4 & meta) != 0; // Get the receivers from the frist 4 bits Receivers receivers = (Receivers)(meta >> 4); // The group and order for this packet are assigned to the trailer of the packet, as // the header is reserved for frame formation int orderId = PullPacketOrderId(packet); int groupId = PullPacketGroupId(packet); ulong uniqueId = PullPacketUniqueId(packet, endPacket); // Check to see if this should respond to the sender that this packet has been received if (reliable && !confirmationPacket) { #if DEEP_LOGGING Logging.BMSLog.Log($">>>>>>>>>>>>>>>>>>>>>>>>>>> SEND CONFIRM: {uniqueId}"); #endif byte[] confirmation = new byte[sizeof(ulong) + sizeof(int) + sizeof(int) + sizeof(byte)]; Buffer.BlockCopy(BitConverter.GetBytes(uniqueId), 0, confirmation, 0, sizeof(ulong)); Buffer.BlockCopy(BitConverter.GetBytes(groupId), 0, confirmation, sizeof(ulong), sizeof(int)); Buffer.BlockCopy(BitConverter.GetBytes(orderId), 0, confirmation, sizeof(ulong) + sizeof(int), sizeof(int)); // Register the confirmation flag in the last byte confirmation[confirmation.Length - 1] = (byte)(meta | 0x4); Client.Send(confirmation, confirmation.Length, sender.IPEndPointHandle); } // Create an instance of a packet struct to be sent off to the packet manager UDPPacket formattedPacket = new UDPPacket(reliable, endPacket, groupId, orderId, uniqueId, packet.CompressBytes(), confirmationPacket, receivers); return(formattedPacket); }
private void HandleHeaderExchanging(BMSByte packet) { if (Websockets.ValidateResponseHeader(headerHash, packet.CompressBytes())) { CompleteHeaderExchange(); } else if (packet.Size >= MINIMUM_FRAME_SIZE) { HandleServerRejection(packet); CancelReadThread(); } else if (packet.Size != 1 || packet[0] != 0) { Disconnect(true); CancelReadThread(); } }
private void PacketSequenceComplete(BMSByte data, int groupId, byte receivers, bool isReliable) { // Pull the frame from the sent message FrameStream frame = Factory.DecodeMessage(data.CompressBytes(), false, groupId, currentReadingPlayer, receivers); if (isReliable) { frame.ExtractReliableId(); // TODO: If the current reliable index for this player is not at // the specified index, then it needs to wait for the correct ordering currentReadingPlayer.WaitReliable(frame); } else { FireRead(frame, currentReadingPlayer); } }
private void SetupClient(BMSByte packet, CSteamID steamId) { if (Players.Count == MaxConnections) { // Tell the client why they are being disconnected Send(Error.CreateErrorMessage(Time.Timestep, "Max Players Reached On Server", false, MessageGroupIds.MAX_CONNECTIONS, true)); // Send the close connection frame to the client Send(new ConnectionClose(Time.Timestep, false, Receivers.Target, MessageGroupIds.DISCONNECT, false)); return; } else if (!AcceptingConnections) { // Tell the client why they are being disconnected Send(Error.CreateErrorMessage(Time.Timestep, "The server is busy and not accepting connections", false, MessageGroupIds.MAX_CONNECTIONS, true)); // Send the close connection frame to the client Send(new ConnectionClose(Time.Timestep, false, Receivers.Target, MessageGroupIds.DISCONNECT, false)); return; } // Validate that the connection headers are properly formatted byte[] response = Websockets.ValidateConnectionHeader(packet.CompressBytes()); // The response will be null if the header sent is invalid, if so then disconnect client as they are sending invalid headers if (response == null) { return; } SteamNetworkingPlayer player = new SteamNetworkingPlayer(ServerPlayerCounter++, steamId, false, this); // If all is in order then send the validated response to the client Client.Send(response, response.Length, steamId); OnPlayerConnected(player); steamPlayers.Add(steamId, player); // The player has successfully connected player.Connected = true; }
public void AppendBytesRemoveStart3Add3ToEnd() { int removeSize = 3; byte[] data = new byte[] { 1, 8, 9, 34, 255, 0, 33, 66, 100, 128 }; var cache = new BMSByte(); cache.Append(data); cache.RemoveStart(removeSize); byte[] trailer = new byte[] { 9, 3, 9 }; cache.Append(trailer); byte[] response = cache.CompressBytes(); for (int i = removeSize; i < data.Length; i++) { Assert.AreEqual(data[i], response[i - removeSize]); Assert.AreEqual(data[i], cache[i - removeSize]); } for (int i = trailer.Length - 1; i >= 0; i--) { Assert.AreEqual(trailer[i], response[response.Length - trailer.Length + i]); } }
private void HandleClientAcceptance(BMSByte packet, string incomingEndpoint, IPEndPoint groupEP) { // Validate that the connection headers are properly formatted byte[] response = Websockets.ValidateConnectionHeader(packet.CompressBytes()); // The response will be null if the header sent is invalid, if so then disconnect client as they are sending invalid headers if (response == null) { return; } var player = new UDPNetworkingPlayer(ServerPlayerCounter++, incomingEndpoint, false, groupEP, this); // If all is in order then send the validated response to the client Client.Send(response, response.Length, groupEP); OnPlayerConnected(player); udpPlayers.Add(incomingEndpoint, player); // The player has successfully connected player.Connected = true; }
private void PacketSequenceComplete(BMSByte data, int groupId, byte receivers) { // Pull the frame from the sent message FrameStream frame = Factory.DecodeMessage(data.CompressBytes(), false, groupId, currentReadingPlayer, receivers); // Check for default messages if (frame is Text) { // This packet is sent if the player did not receive it's network id if (frame.GroupId == MessageGroupIds.NETWORK_ID_REQUEST) { currentReadingPlayer.InstanceGuid = frame.ToString(); OnPlayerGuidAssigned(currentReadingPlayer); // If so, just resend the player id writeBuffer.Clear(); writeBuffer.Append(BitConverter.GetBytes(currentReadingPlayer.NetworkId)); Send(currentReadingPlayer, new Binary(Time.Timestep, false, writeBuffer, Receivers.Target, MessageGroupIds.NETWORK_ID_REQUEST, false), true); SendBuffer(currentReadingPlayer); return; } } if (frame is ConnectionClose) { Send(currentReadingPlayer, new ConnectionClose(Time.Timestep, false, Receivers.Server, MessageGroupIds.DISCONNECT, false), false); Disconnect(currentReadingPlayer, false); CleanupDisconnections(); return; } // Send an event off that a packet has been read OnMessageReceived(currentReadingPlayer, frame); }
/// <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 ReadClients() { IPEndPoint groupEP = new IPEndPoint(IPAddress.Any, 0); string incomingEndpoint = string.Empty; 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 { // 如果出错, 就查找该IP PROT的玩家,将该玩家踢掉 UDPNetworkingPlayer player; if (udpPlayers.TryGetValue(incomingEndpoint, out player)) { FinalizeRemovePlayer(player, true); } continue; } //检查以确保收到消息 // Check to make sure a message was received if (packet == null || packet.Size <= 0) { continue; } //如果玩家列表里不包含该包的发送者 if (!udpPlayers.ContainsKey(incomingEndpoint)) { // 创建该发送者的结构体保存 UDPNetworkingPlayer SetupClient(packet, incomingEndpoint, groupEP); continue; } else { currentReadingPlayer = udpPlayers[incomingEndpoint]; if (!currentReadingPlayer.Accepted && !currentReadingPlayer.PendingAccepted) { //响应验证可能会被丢弃 //检查客户端是否正在重新发送响应 // It is possible that the response validation was dropped so // check if the client is resending for a response byte[] response = Websockets.ValidateConnectionHeader(packet.CompressBytes()); //客户端再次发送连接请求 // The client has sent the connection request again if (response != null) { Client.Send(response, response.Length, groupEP); continue; } else { // 将该玩家设置为等待接受确认 currentReadingPlayer.PendingAccepted = true; // 读取该玩家发来的数据包 ReadPacket(packet); } } else { //由于Forge网络协议,数据包唯一的时间1 //将是71,第二个数据包是69是强制断开连接 // Due to the Forge Networking protocol, the only time that packet 1 // will be 71 and the second packet be 69 is a forced disconnect reconnect if (packet[0] == 71 && packet[1] == 69) { udpPlayers.Remove(currentReadingPlayer.Ip + "+" + currentReadingPlayer.Port); FinalizeRemovePlayer(currentReadingPlayer, true); continue; } // 设置玩家最好ping时间 currentReadingPlayer.Ping(); // 读取该玩家发来的数据包 ReadPacket(packet); } } } }
/// <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> private void ReadClients() { CSteamID messageFrom = default(CSteamID); 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 uint msgSize = 0; if (SteamNetworking.IsP2PPacketAvailable(out msgSize)) { packet = Client.Receive(msgSize, out messageFrom); } else { Thread.Sleep(1); continue; } if (PacketLossSimulation > 0.0f && new Random().NextDouble() <= PacketLossSimulation) { // Skip this message continue; } BandwidthIn += (ulong)packet.Size; } catch (Exception e) { Logging.BMSLog.LogException(e); SteamNetworkingPlayer player; if (steamPlayers.TryGetValue(messageFrom, out player)) { FinalizeRemovePlayer(player, true); } continue; } // Check to make sure a message was received if (packet == null || packet.Size <= 0) { continue; } if (!steamPlayers.ContainsKey(messageFrom)) { SetupClient(packet, messageFrom); continue; } else { currentReadingPlayer = steamPlayers[messageFrom]; if (!currentReadingPlayer.Accepted && !currentReadingPlayer.PendingAccepted) { // It is possible that the response validation was dropped so // check if the client is resending for a response byte[] response = Websockets.ValidateConnectionHeader(packet.CompressBytes()); // The client has sent the connection request again if (response != null) { Client.Send(response, response.Length, messageFrom, EP2PSend.k_EP2PSendReliable); continue; } else { currentReadingPlayer.PendingAccepted = true; ReadPacket(packet); } } else { // Due to the Forge Networking protocol, the only time that packet 1 // will be 71 and the second packet be 69 is a forced disconnect reconnect if (packet[0] == 71 && packet[1] == 69) { Logging.BMSLog.LogFormat("Received packet[0]=71 & packet[1]=69"); steamPlayers.Remove(messageFrom); FinalizeRemovePlayer(currentReadingPlayer, true); continue; } currentReadingPlayer.Ping(); ReadPacket(packet); } } } }
/// <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> private void ReadNetwork() { CSteamID messageFrom = default(CSteamID); 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 { uint msgSize = 0; if (SteamNetworking.IsP2PPacketAvailable(out msgSize)) { packet = Client.Receive(msgSize, out messageFrom); } else { Thread.Sleep(1); continue; } // Read a packet from the network 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; } // 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) { Logging.BMSLog.LogWarning("DISCONNECTED: RECEIVED UNKNOWN PACKET BEFORE HEADERS WERE EXCHANGED!"); Disconnect(true); break; } else { continue; } } else { if (packet.Size < 17) { continue; } // 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); } }
/// <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); } }
/// <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> private void ReadClients() { IPEndPoint groupEP = new IPEndPoint(IPAddress.Any, 0); string incomingEndpoint = string.Empty; 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 { UDPNetworkingPlayer player; if (udpPlayers.TryGetValue(incomingEndpoint, out player)) { FinalizeRemovePlayer(player, true); } continue; } // Check to make sure a message was received if (packet == null || packet.Size <= 0) { continue; } if (!udpPlayers.ContainsKey(incomingEndpoint)) { SetupClient(packet, incomingEndpoint, groupEP); continue; } else { currentReadingPlayer = udpPlayers[incomingEndpoint]; if (!currentReadingPlayer.Accepted && !currentReadingPlayer.PendingAccepted) { // It is possible that the response validation was dropped so // check if the client is resending for a response byte[] response = Websockets.ValidateConnectionHeader(packet.CompressBytes()); // The client has sent the connection request again if (response != null) { Client.Send(response, response.Length, groupEP); continue; } else { currentReadingPlayer.PendingAccepted = true; ReadPacket(packet); } } else { // Due to the Forge Networking protocol, the only time that packet 1 // will be 71 and the second packet be 69 is a forced disconnect reconnect if (packet[0] == 71 && packet[1] == 69) { udpPlayers.Remove(currentReadingPlayer.Ip + "+" + currentReadingPlayer.Port); FinalizeRemovePlayer(currentReadingPlayer, true); continue; } currentReadingPlayer.Ping(); ReadPacket(packet); } } } }
/// <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> 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 >= MINIMUM_FRAME_SIZE) { // The server sent us a message before sending a responseheader to validate // This happens if the server is not accepting connections or the max connection count has been reached // We will get two messages. The first one is either a MAX_CONNECTIONS or NOT_ACCEPT_CONNECTIONS group message. // The second one will be the DISCONNECT message UDPPacket formattedPacket = TranscodePacket(Server, packet); if (formattedPacket.groupId == MessageGroupIds.MAX_CONNECTIONS) { Logging.BMSLog.LogWarning("Max Players Reached On Server"); // Wait for the second message (Disconnect) continue; } if (formattedPacket.groupId == MessageGroupIds.NOT_ACCEPT_CONNECTIONS) { Logging.BMSLog.LogWarning("The server is busy and not accepting connections"); // Wait for the second message (Disconnect) continue; } if (formattedPacket.groupId == MessageGroupIds.DISCONNECT) { CloseConnection(); return; } // Received something unexpected so do the same thing as the if below Disconnect(true); break; } else if (packet.Size != 1 || packet[0] != 0) { Disconnect(true); break; } else { continue; } } else { if (packet.Size < MINIMUM_FRAME_SIZE) { continue; } // 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; } if (formattedPacket.groupId == MessageGroupIds.AUTHENTICATION_FAILURE) { Logging.BMSLog.LogWarning("The server rejected the authentication attempt"); // Wait for the second message (Disconnect) 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); } }
/// <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> private void ReadClients() { IPEndPoint groupEP = new IPEndPoint(IPAddress.Any, 0); string incomingEndpoint = string.Empty; 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 (Exception ex) when(!(ex is SocketException)) { Console.WriteLine($"Error in ReadClients() infinite loop, error was {ex.Message}"); UDPNetworkingPlayer player; if (udpPlayers.TryGetValue(incomingEndpoint, out player)) { Console.WriteLine($"Following the error, player '{player.NetworkId}' will be removed"); FinalizeRemovePlayer(player, true); } continue; } // Check to make sure a message was received if (packet == null || packet.Size <= 0) { continue; } if (!udpPlayers.ContainsKey(incomingEndpoint)) { SetupClient(packet, incomingEndpoint, groupEP); continue; } else { currentReadingPlayer = udpPlayers[incomingEndpoint]; if (!currentReadingPlayer.Accepted && !currentReadingPlayer.PendingAccepted) { // It is possible that the response validation was dropped so // check if the client is resending for a response byte[] response = Websockets.ValidateConnectionHeader(packet.CompressBytes()); // The client has sent the connection request again if (response != null) { Client.Send(response, response.Length, groupEP); continue; } else { currentReadingPlayer.PendingAccepted = true; ReadPacket(packet); } } else { currentReadingPlayer.Ping(); ReadPacket(packet); } } } }
/// <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> private void ReadClients() { IPEndPoint groupEP = new IPEndPoint(IPAddress.Any, 0); string incomingEndpoint = string.Empty; 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 { if (udpPlayers.ContainsKey(incomingEndpoint)) { Disconnect(udpPlayers[incomingEndpoint], true); CleanupDisconnections(); } continue; } // Check to make sure a message was received if (packet == null || packet.Size <= 0) { continue; } if (!udpPlayers.ContainsKey(incomingEndpoint)) { SetupClient(packet, incomingEndpoint, groupEP); continue; } else { currentReadingPlayer = udpPlayers[incomingEndpoint]; if (!currentReadingPlayer.Accepted && !currentReadingPlayer.PendingAccpeted) { // It is possible that the response validation was dropped so // check if the client is resending for a response byte[] response = Websockets.ValidateConnectionHeader(packet.CompressBytes()); // The client has sent the connection request again if (response != null) { Client.Send(response, response.Length, groupEP); continue; } else { currentReadingPlayer.PendingAccpeted = true; ReadPacket(packet); } } else { ReadPacket(packet); } } } }