/// <summary> /// Used to clean up the target composer from memory /// </summary> /// <param name="composer">The composer that has completed</param> private void ComposerCompleted(UDPPacketComposer composer) { lock (pendingComposers) { pendingComposers.Remove(composer); } }
/// <summary> /// Star the next composer available composer /// </summary> private void NextComposerInQueue() { // If there are not currently any queued composers then we can stop here if (reliableComposers.Count == 0) { return; } // If there are no more composers in queue, end if (!nextComposerReady) { return; } // Prevent any queued composers from starting until this one finishes nextComposerReady = false; lock (reliableComposers) { currentComposer = reliableComposers[0]; } if (!composerReady && Networker.IsBound && !NetWorker.ExitingApplication) { // Run this on a separate thread so that it doesn't interfere with the reading thread Task.Queue(() => { while (Networker.IsBound && !Disconnected) { if (nextComposerReady) { Task.Sleep(10); continue; } do { lock (currentComposer.PendingPackets) { if (currentComposer.PendingPackets.Count > 0) { if (Networker.LatencySimulation > 0) { Task.Sleep(Networker.LatencySimulation); } currentComposer.ResendPackets(); } } // TODO: Wait the latency for this Task.Sleep(10); } while (!currentComposer.Player.Disconnected && currentComposer.PendingPackets.Count > 0 && Networker.IsBound && !NetWorker.ExitingApplication); } }); composerReady = true; } }
/// <summary> /// Used to clean up the target composer from memory /// </summary> /// <param name="composer">The composer that has completed</param> protected void ComposerCompleted(UDPPacketComposer composer) { #if DEEP_LOGGING Logging.BMSLog.Log($"<<<<<<<<<<<<<<<<<<<<<<<<<<< CONFIRMING: {composer.Frame.UniqueId}"); #endif lock (pendingComposers) { pendingComposers.Remove(composer); } }
public override void Send(FrameStream frame, bool reliable = false) { UDPPacketComposer composer = new UDPPacketComposer(); // If this message is reliable then make sure to keep a reference to the composer // so that there are not any run-away threads if (reliable) { composer.completed += ComposerCompleted; pendingComposers.Add(composer); } composer.Init(this, ServerPlayer, frame, reliable); }
public void QueueComposer(UDPPacketComposer composer) { if (Disconnected) { return; } lock (reliableComposers) { reliableComposers.Add(composer); } // Start the reliable send thread on this composer NextComposerInQueue(); }
public void Send(NetworkingPlayer player, FrameStream frame, bool reliable = false) { UDPPacketComposer composer = new UDPPacketComposer(this, player, frame, reliable); // If this message is reliable then make sure to keep a reference to the composer // so that there are not any run-away threads if (reliable) { lock (pendingComposers) { // Use the completed event to clean up the object from memory composer.completed += ComposerCompleted; pendingComposers.Add(composer); } } }
public override void Send(FrameStream frame, bool reliable = false) { UDPPacketComposer composer = new UDPPacketComposer(); // If this message is reliable then make sure to keep a reference to the composer // so that there are not any run-away threads if (reliable) { // Use the completed event to clean up the object from memory composer.completed += ComposerCompleted; pendingComposers.Add(composer); } //TODO: New constructor for setting up callbacks before regular constructor (as seen above) composer.Init(this, Server, frame, reliable); }
private void HandleMaximumClientPacketResponse(string incomingEndpoint, IPEndPoint groupEP) { // Tell the client why they are being disconnected Error frame = Error.CreateErrorMessage(Time.Timestep, "Max Players Reached On Server", false, MessageGroupIds.MAX_CONNECTIONS, false); var playerToDisconnect = new UDPNetworkingPlayer(ServerPlayerCounter++, incomingEndpoint, false, groupEP, this); UDPPacketComposer.SendNewUDPPacket(this, playerToDisconnect, frame, false); // Send the close connection frame to the client UDPPacketComposer.SendNewUDPPacket(this, playerToDisconnect, new ConnectionClose(Time.Timestep, false, Receivers.Target, MessageGroupIds.DISCONNECT, false), false); }
private void HandleNotAcceptingConnectionsPacketResponse(string incomingEndpoint, IPEndPoint groupEP) { // Tell the client why they are being disconnected var frame = Error.CreateErrorMessage(Time.Timestep, "The server is busy and not accepting connections", false, MessageGroupIds.NOT_ACCEPT_CONNECTIONS, false); var playerToDisconnect = new UDPNetworkingPlayer(ServerPlayerCounter++, incomingEndpoint, false, groupEP, this); UDPPacketComposer.SendNewUDPPacket(this, playerToDisconnect, frame, false); // Send the close connection frame to the client UDPPacketComposer.SendNewUDPPacket(this, playerToDisconnect, new ConnectionClose(Time.Timestep, false, Receivers.Target, MessageGroupIds.DISCONNECT, false), false); }
public override void Send(FrameStream frame, bool reliable = false) { UDPPacketComposer composer = new UDPPacketComposer(); //如果这个信息是可靠的,那么一定要保持对作曲家的引用 //这样就没有任何失控的线程 // If this message is reliable then make sure to keep a reference to the composer // so that there are not any run-away threads if (reliable) { //使用完成的事件从内存中清理对象 // Use the completed event to clean up the object from memory composer.completed += ComposerCompleted; pendingComposers.Add(composer); } // TODO:在正则构造函数之前设置回调的新构造函数(如上所示) //TODO: New constructor for setting up callbacks before regular constructor (as seen above) composer.Init(this, Server, frame, reliable); }
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 var frame = Error.CreateErrorMessage(Time.Timestep, "Max Players Reached On Server", false, MessageGroupIds.MAX_CONNECTIONS, true); var playerToDisconnect = new UDPNetworkingPlayer(ServerPlayerCounter++, incomingEndpoint, false, groupEP, this); var composer = new UDPPacketComposer(this, playerToDisconnect, frame, false); // Send the close connection frame to the client composer = new UDPPacketComposer(this, playerToDisconnect, new ConnectionClose(Time.Timestep, false, Receivers.Target, MessageGroupIds.DISCONNECT, false), false); return; } else if (!AcceptingConnections) { // Tell the client why they are being disconnected var frame = Error.CreateErrorMessage(Time.Timestep, "The server is busy and not accepting connections", false, MessageGroupIds.NOT_ACCEPT_CONNECTIONS, true); var playerToDisconnect = new UDPNetworkingPlayer(ServerPlayerCounter++, incomingEndpoint, false, groupEP, this); var composer = new UDPPacketComposer(this, playerToDisconnect, frame, false); // Send the close connection frame to the client composer = new UDPPacketComposer(this, playerToDisconnect, new ConnectionClose(Time.Timestep, false, Receivers.Target, MessageGroupIds.DISCONNECT, false), 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; }