1
0
mirror of https://github.com/lidgren/lidgren-network-gen3.git synced 2026-05-06 02:11:06 +09:00

ConnectionLatencyUpdated message type added; WriteTime() ReadTime() added

This commit is contained in:
lidgren
2010-12-20 10:35:51 +00:00
parent 772d80835b
commit 330c5cf83e
11 changed files with 85 additions and 25 deletions

View File

@@ -183,7 +183,7 @@ namespace Lidgren.Network
m_peer.m_handshakes.Remove(m_remoteEndpoint); // TODO: make this more thread safe? we're on user thread
}
internal void ReceivedHandshake(NetMessageType tp, int ptr, int payloadLength)
internal void ReceivedHandshake(double now, NetMessageType tp, int ptr, int payloadLength)
{
m_peer.VerifyNetworkThread();
@@ -211,6 +211,7 @@ namespace Lidgren.Network
{
// ok, let's not add connection just yet
NetIncomingMessage appMsg = m_peer.CreateIncomingMessage(NetIncomingMessageType.ConnectionApproval, (m_remoteHailMessage == null ? 0 : m_remoteHailMessage.LengthBytes));
appMsg.m_receiveTime = now;
appMsg.m_senderConnection = this;
appMsg.m_senderEndpoint = this.m_remoteEndpoint;
if (m_remoteHailMessage != null)

View File

@@ -9,11 +9,19 @@ namespace Lidgren.Network
private float m_averageRoundtripTime;
private float m_timeoutDeadline = float.MaxValue;
// local time value + m_remoteTimeOffset = remote time value
internal double m_remoteTimeOffset;
/// <summary>
/// Gets the current average roundtrip time in seconds
/// </summary>
public float AverageRoundtripTime { get { return m_averageRoundtripTime; } }
internal double GetLocalTime(double remoteTimeStamp)
{
return remoteTimeStamp - m_remoteTimeOffset;
}
internal void InitializePing()
{
// randomize ping sent time (0.25 - 1.0 x ping interval)
@@ -27,11 +35,10 @@ namespace Lidgren.Network
m_peer.VerifyNetworkThread();
m_sentPingNumber++;
if (m_sentPingNumber >= 256)
m_sentPingNumber = 0;
m_sentPingTime = (float)NetTime.Now;
NetOutgoingMessage om = m_peer.CreateMessage(1);
om.Write((byte)m_sentPingNumber);
om.Write((byte)m_sentPingNumber); // truncating to 0-255
om.m_messageType = NetMessageType.Ping;
int len = om.Encode(m_peer.m_sendBuffer, 0, 0);
@@ -45,20 +52,22 @@ namespace Lidgren.Network
{
m_peer.VerifyNetworkThread();
NetOutgoingMessage om = m_peer.CreateMessage(1);
NetOutgoingMessage om = m_peer.CreateMessage(5);
om.Write((byte)pingNumber);
om.Write((float)NetTime.Now); // we should update this value to reflect the exact point in time the packet is SENT
om.m_messageType = NetMessageType.Pong;
int len = om.Encode(m_peer.m_sendBuffer, 0, 0);
bool connectionReset;
m_peer.SendPacket(len, m_remoteEndpoint, 1, out connectionReset);
m_statistics.PacketSent(len, 1);
}
internal void ReceivedPong(float now, int pongNumber)
internal void ReceivedPong(float now, int pongNumber, float remoteSendTime)
{
if (pongNumber != m_sentPingNumber)
if ((byte)pongNumber != (byte)m_sentPingNumber)
{
m_peer.LogVerbose("Ping/Pong mismatch; dropped message?");
return;
@@ -69,15 +78,20 @@ namespace Lidgren.Network
float rtt = now - m_sentPingTime;
NetException.Assert(rtt >= 0);
double diff = (remoteSendTime + (rtt / 2.0)) - now;
if (m_averageRoundtripTime < 0)
{
m_remoteTimeOffset = diff;
m_averageRoundtripTime = rtt; // initial estimate
m_peer.LogDebug("Initiated average roundtrip time to " + NetTime.ToReadable(m_averageRoundtripTime));
m_peer.LogDebug("Initiated average roundtrip time to " + NetTime.ToReadable(m_averageRoundtripTime) + " Server time is: " + (now + diff));
}
else
{
m_averageRoundtripTime = (m_averageRoundtripTime * 0.7f) + (float)(rtt * 0.3f);
m_peer.LogVerbose("Updated average roundtrip time to " + NetTime.ToReadable(m_averageRoundtripTime));
m_remoteTimeOffset = ((m_remoteTimeOffset * (double)(m_sentPingNumber - 1)) + diff) / (double)m_sentPingNumber;
m_peer.LogVerbose("Updated average roundtrip time to " + NetTime.ToReadable(m_averageRoundtripTime) + ", server time to " + (now + m_remoteTimeOffset) + " (ie. diff " + m_remoteTimeOffset + ")");
}
// update resend delay for all channels
@@ -89,7 +103,17 @@ namespace Lidgren.Network
rchan.m_resendDelay = resendDelay;
}
m_peer.LogVerbose("Timeout deadline pushed to " + m_timeoutDeadline);
// m_peer.LogVerbose("Timeout deadline pushed to " + m_timeoutDeadline);
// notify the application that average rtt changed
if (m_peer.m_configuration.IsMessageTypeEnabled(NetIncomingMessageType.ConnectionLatencyUpdated))
{
NetIncomingMessage update = m_peer.CreateIncomingMessage(NetIncomingMessageType.ConnectionLatencyUpdated, 4);
update.m_senderConnection = this;
update.m_senderEndpoint = this.m_remoteEndpoint;
update.Write(rtt);
m_peer.ReleaseMessage(update);
}
}
}
}

View File

@@ -26,7 +26,7 @@ namespace Lidgren.Network
internal void InitExpandMTU(double now)
{
m_lastSentMTUAttemptTime = now + m_peerConfiguration.m_expandMTUFrequency + 1.0f; // wait a tiny bit before starting to expand mtu
m_lastSentMTUAttemptTime = now + m_peerConfiguration.m_expandMTUFrequency + 1.5f + m_averageRoundtripTime; // wait a tiny bit before starting to expand mtu
m_largestSuccessfulMTU = 512;
m_smallestFailedMTU = -1;
m_currentMTU = m_peerConfiguration.MaximumTransmissionUnit;

View File

@@ -138,10 +138,10 @@ namespace Lidgren.Network
{
if (now > m_sentPingTime + m_peer.m_configuration.m_pingInterval)
SendPing();
}
// handle expand mtu
MTUExpansionHeartbeat(now);
// handle expand mtu
MTUExpansionHeartbeat(now);
}
if (m_disconnectRequested)
{
@@ -352,8 +352,10 @@ namespace Lidgren.Network
SendPong(pingNr);
break;
case NetMessageType.Pong:
int pongNr = m_peer.m_receiveBuffer[ptr++];
ReceivedPong(now, pongNr);
NetIncomingMessage pmsg = m_peer.SetupReadHelperMessage(ptr, payloadLength);
int pongNr = pmsg.ReadByte();
float remoteSendTime = pmsg.ReadSingle();
ReceivedPong(now, pongNr, remoteSendTime);
break;
case NetMessageType.ExpandMTURequest:
SendMTUSuccess(payloadLength);

View File

@@ -465,6 +465,20 @@ namespace Lidgren.Network
return new IPEndPoint(address, port);
}
/// <summary>
/// Reads a value, in local time comparable to NetTime.Now, written using WriteTime()
/// Must have a connected sender
/// </summary>
public double ReadTime(bool highPrecision)
{
double remoteTime = (highPrecision ? ReadDouble() : (double)ReadSingle());
if (m_senderConnection == null)
throw new NetException("Cannot call ReadTime() on message without a connected sender (ie. unconnected messages)");
return remoteTime - m_senderConnection.m_remoteTimeOffset;
}
/// <summary>
/// Pads data with enough bits to reach a full byte. Decreases cpu usage for subsequent byte writes.
/// </summary>

View File

@@ -36,6 +36,7 @@ namespace Lidgren.Network
internal int m_sequenceNumber;
internal NetMessageType m_receivedMessageType;
internal bool m_isFragment;
internal double m_receiveTime;
/// <summary>
/// Gets the type of this incoming message
@@ -62,6 +63,11 @@ namespace Lidgren.Network
/// </summary>
public NetConnection SenderConnection { get { return m_senderConnection; } }
/// <summary>
/// What local time the message was received from the network
/// </summary>
public double ReceiveTime { get { return m_receiveTime; } }
/// <summary>
/// Gets the length of the message payload in bytes
/// </summary>

View File

@@ -42,5 +42,6 @@ namespace Lidgren.Network
WarningMessage = 1 << 9, // Data (string)
ErrorMessage = 1 << 10, // Data (string)
NatIntroductionSuccess = 1 << 11, // Data (as passed to master server)
ConnectionLatencyUpdated = 1 << 12, // Seconds as a Single
}
}

View File

@@ -534,6 +534,17 @@ namespace Lidgren.Network
Write((ushort)endPoint.Port);
}
/// <summary>
/// Writes the local time to a message; readable (and convertable to local time) by the remote host using ReadTime()
/// </summary>
public void WriteTime(double localTime, bool highPrecision)
{
if (highPrecision)
Write(localTime);
else
Write((float)localTime);
}
/// <summary>
/// Pads data with enough bits to reach a full byte. Decreases cpu usage for subsequent byte writes.
/// </summary>

View File

@@ -124,7 +124,7 @@ namespace Lidgren.Network
Buffer.BlockCopy(im.m_data, ptr, info.Data, offset, im.LengthBytes - ptr);
int cnt = info.ReceivedChunks.Count();
//Console.WriteLine("Found fragment #" + chunkNumber + " in group " + group + " offset " + offset + " of total bits " + totalBits + " (total chunks done " + cnt + ")");
//LogVerbose("Found fragment #" + chunkNumber + " in group " + group + " offset " + offset + " of total bits " + totalBits + " (total chunks done " + cnt + ")");
LogVerbose("Received fragment " + chunkNumber + " of " + totalNumChunks + " (" + cnt + " chunks received)");

View File

@@ -43,9 +43,6 @@ namespace Lidgren.Network
{
NetException.Assert(msg.m_incomingMessageType != NetIncomingMessageType.Error);
if (msg.MessageType == NetIncomingMessageType.UnconnectedData)
Console.WriteLine("x");
if (msg.m_isFragment)
{
HandleReleasedFragment(msg);
@@ -306,6 +303,7 @@ namespace Lidgren.Network
NetConnection sender = null;
m_connectionLookup.TryGetValue(ipsender, out sender);
double receiveTime = NetTime.Now;
//
// parse packet into messages
//
@@ -344,7 +342,7 @@ namespace Lidgren.Network
if (sender != null)
sender.ReceivedLibraryMessage(tp, ptr, payloadByteLength);
else
ReceivedUnconnectedLibraryMessage(ipsender, tp, ptr, payloadByteLength);
ReceivedUnconnectedLibraryMessage(receiveTime, ipsender, tp, ptr, payloadByteLength);
}
else
{
@@ -353,6 +351,7 @@ namespace Lidgren.Network
NetIncomingMessage msg = CreateIncomingMessage(NetIncomingMessageType.Data, payloadByteLength);
msg.m_isFragment = isFragment;
msg.m_receiveTime = receiveTime;
msg.m_sequenceNumber = sequenceNumber;
msg.m_receivedMessageType = tp;
msg.m_senderConnection = sender;
@@ -390,12 +389,12 @@ namespace Lidgren.Network
}
}
private void ReceivedUnconnectedLibraryMessage(IPEndPoint senderEndpoint, NetMessageType tp, int ptr, int payloadByteLength)
private void ReceivedUnconnectedLibraryMessage(double now, IPEndPoint senderEndpoint, NetMessageType tp, int ptr, int payloadByteLength)
{
NetConnection shake;
if (m_handshakes.TryGetValue(senderEndpoint, out shake))
{
shake.ReceivedHandshake(tp, ptr, payloadByteLength);
shake.ReceivedHandshake(now, tp, ptr, payloadByteLength);
return;
}
@@ -410,6 +409,7 @@ namespace Lidgren.Network
NetIncomingMessage dm = CreateIncomingMessage(NetIncomingMessageType.DiscoveryRequest, payloadByteLength);
if (payloadByteLength > 0)
Buffer.BlockCopy(m_receiveBuffer, ptr, dm.m_data, 0, payloadByteLength);
dm.m_receiveTime = now;
dm.m_bitLength = payloadByteLength * 8;
dm.m_senderEndpoint = senderEndpoint;
ReleaseMessage(dm);
@@ -422,6 +422,7 @@ namespace Lidgren.Network
NetIncomingMessage dr = CreateIncomingMessage(NetIncomingMessageType.DiscoveryResponse, payloadByteLength);
if (payloadByteLength > 0)
Buffer.BlockCopy(m_receiveBuffer, ptr, dr.m_data, 0, payloadByteLength);
dr.m_receiveTime = now;
dr.m_bitLength = payloadByteLength * 8;
dr.m_senderEndpoint = senderEndpoint;
ReleaseMessage(dr);
@@ -460,7 +461,7 @@ namespace Lidgren.Network
// Ok, start handshake!
NetConnection conn = new NetConnection(this, senderEndpoint);
m_handshakes.Add(senderEndpoint, conn);
conn.ReceivedHandshake(tp, ptr, payloadByteLength);
conn.ReceivedHandshake(now, tp, ptr, payloadByteLength);
return;
}

View File

@@ -67,7 +67,7 @@ namespace Lidgren.Network
//
// default values
//
m_disabledTypes = NetIncomingMessageType.ConnectionApproval | NetIncomingMessageType.UnconnectedData | NetIncomingMessageType.VerboseDebugMessage;
m_disabledTypes = NetIncomingMessageType.ConnectionApproval | NetIncomingMessageType.UnconnectedData | NetIncomingMessageType.VerboseDebugMessage | NetIncomingMessageType.ConnectionLatencyUpdated;
m_networkThreadName = "Lidgren network thread";
m_localAddress = IPAddress.Any;
m_port = 0;