mirror of
https://github.com/MirrorNetworking/Mirror.git
synced 2024-11-18 11:00:32 +00:00
feature: NetworkConnectionToClient.rtt via Ping & Pong Messages (#3545)
* NetworkConnectionToClient: send Ping message every PingFrequency * breaking: NetworkPing/PongMessage .clientTime renamed to .localTime because it'll be used in both directions * Server->Client->Server Ping/Pong messages and rtt * don't ping in host mode * adjust tests * TODO
This commit is contained in:
parent
398d2e6d2c
commit
483006eadc
@ -29,6 +29,9 @@ internal override void Send(ArraySegment<byte> segment, int channelId = Channels
|
|||||||
// true because local connections never timeout
|
// true because local connections never timeout
|
||||||
internal override bool IsAlive(float timeout) => true;
|
internal override bool IsAlive(float timeout) => true;
|
||||||
|
|
||||||
|
// don't ping host client in host mode
|
||||||
|
protected override void UpdatePing() {}
|
||||||
|
|
||||||
internal void DisconnectInternal()
|
internal void DisconnectInternal()
|
||||||
{
|
{
|
||||||
// set not ready and handle clientscene disconnect in any case
|
// set not ready and handle clientscene disconnect in any case
|
||||||
|
@ -111,22 +111,21 @@ public struct EntityStateMessage : NetworkMessage
|
|||||||
public ArraySegment<byte> payload;
|
public ArraySegment<byte> payload;
|
||||||
}
|
}
|
||||||
|
|
||||||
// A client sends this message to the server
|
// whoever wants to measure rtt, sends this to the other end.
|
||||||
// to calculate RTT and synchronize time
|
|
||||||
public struct NetworkPingMessage : NetworkMessage
|
public struct NetworkPingMessage : NetworkMessage
|
||||||
{
|
{
|
||||||
public double clientTime;
|
public double localTime;
|
||||||
|
|
||||||
public NetworkPingMessage(double value)
|
public NetworkPingMessage(double value)
|
||||||
{
|
{
|
||||||
clientTime = value;
|
localTime = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// The server responds with this message
|
// the other end responds with this message.
|
||||||
// The client can use this to calculate RTT and sync time
|
// we can use this to calculate rtt.
|
||||||
public struct NetworkPongMessage : NetworkMessage
|
public struct NetworkPongMessage : NetworkMessage
|
||||||
{
|
{
|
||||||
public double clientTime;
|
public double localTime;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -471,6 +471,7 @@ internal static void RegisterMessageHandlers(bool hostMode)
|
|||||||
RegisterHandler<ObjectDestroyMessage>(OnObjectDestroy);
|
RegisterHandler<ObjectDestroyMessage>(OnObjectDestroy);
|
||||||
RegisterHandler<ObjectHideMessage>(OnObjectHide);
|
RegisterHandler<ObjectHideMessage>(OnObjectHide);
|
||||||
RegisterHandler<NetworkPongMessage>(NetworkTime.OnClientPong, false);
|
RegisterHandler<NetworkPongMessage>(NetworkTime.OnClientPong, false);
|
||||||
|
RegisterHandler<NetworkPingMessage>(NetworkTime.OnClientPing, false);
|
||||||
RegisterHandler<SpawnMessage>(OnSpawn);
|
RegisterHandler<SpawnMessage>(OnSpawn);
|
||||||
RegisterHandler<ObjectSpawnStartedMessage>(OnObjectSpawnStarted);
|
RegisterHandler<ObjectSpawnStartedMessage>(OnObjectSpawnStarted);
|
||||||
RegisterHandler<ObjectSpawnFinishedMessage>(OnObjectSpawnFinished);
|
RegisterHandler<ObjectSpawnFinishedMessage>(OnObjectSpawnFinished);
|
||||||
|
@ -46,6 +46,14 @@ public class NetworkConnectionToClient : NetworkConnection
|
|||||||
// Snapshot Buffer size limit to avoid ever growing list memory consumption attacks from clients.
|
// Snapshot Buffer size limit to avoid ever growing list memory consumption attacks from clients.
|
||||||
public int snapshotBufferSizeLimit = 64;
|
public int snapshotBufferSizeLimit = 64;
|
||||||
|
|
||||||
|
// ping for rtt (round trip time)
|
||||||
|
// useful for statistics, lag compensation, etc.
|
||||||
|
double lastPingTime = 0;
|
||||||
|
internal ExponentialMovingAverage _rtt = new ExponentialMovingAverage(NetworkTime.PingWindowSize);
|
||||||
|
|
||||||
|
/// <summary>Round trip time (in seconds) that it takes a message to go server->client->server.</summary>
|
||||||
|
public double rtt => _rtt.Value;
|
||||||
|
|
||||||
public NetworkConnectionToClient(int networkConnectionId)
|
public NetworkConnectionToClient(int networkConnectionId)
|
||||||
: base(networkConnectionId)
|
: base(networkConnectionId)
|
||||||
{
|
{
|
||||||
@ -175,12 +183,29 @@ internal void BufferRpc(RpcMessage message, int channelId)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected virtual void UpdatePing()
|
||||||
|
{
|
||||||
|
// localTime (double) instead of Time.time for accuracy over days
|
||||||
|
if (NetworkTime.localTime >= lastPingTime + NetworkTime.PingInterval)
|
||||||
|
{
|
||||||
|
// TODO it would be safer for the server to store the last N
|
||||||
|
// messages' timestamp and only send a message number.
|
||||||
|
// This way client's can't just modify the timestamp.
|
||||||
|
NetworkPingMessage pingMessage = new NetworkPingMessage(NetworkTime.localTime);
|
||||||
|
Send(pingMessage, Channels.Unreliable);
|
||||||
|
lastPingTime = NetworkTime.localTime;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
internal override void Update()
|
internal override void Update()
|
||||||
{
|
{
|
||||||
// send rpc buffers
|
// send rpc buffers
|
||||||
FlushRpcs(reliableRpcs, Channels.Reliable);
|
FlushRpcs(reliableRpcs, Channels.Reliable);
|
||||||
FlushRpcs(unreliableRpcs, Channels.Unreliable);
|
FlushRpcs(unreliableRpcs, Channels.Unreliable);
|
||||||
|
|
||||||
|
// ping client for rtt
|
||||||
|
UpdatePing();
|
||||||
|
|
||||||
// call base update to flush out batched messages
|
// call base update to flush out batched messages
|
||||||
base.Update();
|
base.Update();
|
||||||
}
|
}
|
||||||
|
@ -266,6 +266,7 @@ internal static void RegisterMessageHandlers()
|
|||||||
RegisterHandler<ReadyMessage>(OnClientReadyMessage);
|
RegisterHandler<ReadyMessage>(OnClientReadyMessage);
|
||||||
RegisterHandler<CommandMessage>(OnCommandMessage);
|
RegisterHandler<CommandMessage>(OnCommandMessage);
|
||||||
RegisterHandler<NetworkPingMessage>(NetworkTime.OnServerPing, false);
|
RegisterHandler<NetworkPingMessage>(NetworkTime.OnServerPing, false);
|
||||||
|
RegisterHandler<NetworkPongMessage>(NetworkTime.OnServerPong, false);
|
||||||
RegisterHandler<EntityStateMessage>(OnEntityStateMessage, true);
|
RegisterHandler<EntityStateMessage>(OnEntityStateMessage, true);
|
||||||
RegisterHandler<TimeSnapshotMessage>(OnTimeSnapshotMessage, true);
|
RegisterHandler<TimeSnapshotMessage>(OnTimeSnapshotMessage, true);
|
||||||
}
|
}
|
||||||
|
@ -109,15 +109,16 @@ internal static void UpdateClient()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// client rtt calculation //////////////////////////////////////////////
|
||||||
// executed at the server when we receive a ping message
|
// executed at the server when we receive a ping message
|
||||||
// reply with a pong containing the time from the client
|
// reply with a pong containing the time from the client
|
||||||
// and time from the server
|
// and time from the server
|
||||||
internal static void OnServerPing(NetworkConnectionToClient conn, NetworkPingMessage message)
|
internal static void OnServerPing(NetworkConnectionToClient conn, NetworkPingMessage message)
|
||||||
{
|
{
|
||||||
// Debug.Log($"OnPingServerMessage conn:{conn}");
|
// Debug.Log($"OnServerPing conn:{conn}");
|
||||||
NetworkPongMessage pongMessage = new NetworkPongMessage
|
NetworkPongMessage pongMessage = new NetworkPongMessage
|
||||||
{
|
{
|
||||||
clientTime = message.clientTime,
|
localTime = message.localTime,
|
||||||
};
|
};
|
||||||
conn.Send(pongMessage, Channels.Unreliable);
|
conn.Send(pongMessage, Channels.Unreliable);
|
||||||
}
|
}
|
||||||
@ -128,8 +129,32 @@ internal static void OnServerPing(NetworkConnectionToClient conn, NetworkPingMes
|
|||||||
internal static void OnClientPong(NetworkPongMessage message)
|
internal static void OnClientPong(NetworkPongMessage message)
|
||||||
{
|
{
|
||||||
// how long did this message take to come back
|
// how long did this message take to come back
|
||||||
double newRtt = localTime - message.clientTime;
|
double newRtt = localTime - message.localTime;
|
||||||
_rtt.Add(newRtt);
|
_rtt.Add(newRtt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// server rtt calculation //////////////////////////////////////////////
|
||||||
|
// Executed at the client when we receive a ping message from the server.
|
||||||
|
// in other words, this is for server sided ping + rtt calculation.
|
||||||
|
// reply with a pong containing the time from the server
|
||||||
|
internal static void OnClientPing(NetworkPingMessage message)
|
||||||
|
{
|
||||||
|
// Debug.Log($"OnClientPing conn:{conn}");
|
||||||
|
NetworkPongMessage pongMessage = new NetworkPongMessage
|
||||||
|
{
|
||||||
|
localTime = message.localTime,
|
||||||
|
};
|
||||||
|
NetworkClient.Send(pongMessage, Channels.Unreliable);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Executed at the server when we receive a Pong message back.
|
||||||
|
// find out how long it took since we sent the Ping
|
||||||
|
// and update time offset
|
||||||
|
internal static void OnServerPong(NetworkConnectionToClient conn, NetworkPongMessage message)
|
||||||
|
{
|
||||||
|
// how long did this message take to come back
|
||||||
|
double newRtt = localTime - message.localTime;
|
||||||
|
conn._rtt.Add(newRtt);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,6 +35,7 @@ public void Send_BatchesUntilUpdate()
|
|||||||
{
|
{
|
||||||
// create connection and send
|
// create connection and send
|
||||||
NetworkConnectionToClient connection = new NetworkConnectionToClient(42);
|
NetworkConnectionToClient connection = new NetworkConnectionToClient(42);
|
||||||
|
NetworkTime.PingInterval = float.MaxValue; // disable ping for this test
|
||||||
byte[] message = {0x01, 0x02};
|
byte[] message = {0x01, 0x02};
|
||||||
connection.Send(new ArraySegment<byte>(message));
|
connection.Send(new ArraySegment<byte>(message));
|
||||||
|
|
||||||
@ -63,6 +64,7 @@ public void SendBatchingResetsPreviousWriter()
|
|||||||
|
|
||||||
// create connection
|
// create connection
|
||||||
NetworkConnectionToClient connection = new NetworkConnectionToClient(42);
|
NetworkConnectionToClient connection = new NetworkConnectionToClient(42);
|
||||||
|
NetworkTime.PingInterval = float.MaxValue; // disable ping for this test
|
||||||
|
|
||||||
// send and update big message
|
// send and update big message
|
||||||
byte[] message = {0x01, 0x02};
|
byte[] message = {0x01, 0x02};
|
||||||
|
Loading…
Reference in New Issue
Block a user