Unreliable rpc order and uniquence

Hello Epic,
I have one RPC function called from server to client every 1 second, My questions are: does the order of calling on client guaranteed as the same on the server? and is it guaranteed that, one call on server will only trigger one call on client?(in some bad case I guess router in the network may resent package to client more than one times, so in that case does RPC framework drop the duplicated call gracefully?)

Net PktLoss=1
Net PktOrder=0
Net PktDup=0
Net PktLag=75
Net PktLagVariance=0
p.netshowcorrections 1

use this console variables to create latency

thanks for replying, but my question is about how RPC system handle the network cases, especially for one specified client, will same RPC calls on one actor triggered in correct sequence and in expected uniquence?

If a RPC system have labeld “Id” and “timestamp”, it is possible to handle these cases gracefully, so I am wondering the system in UE4 under the hood, whether I can tell my self don’t bother about it in the application level.

Digged a bit deeper:

void UNetConnection::ReceivedPacket( FBitReader& Reader )
{

  ....
	if( PacketId > InPacketId )
	{
		const int32 PacketsLost = PacketId - InPacketId - 1;
		
		if ( PacketsLost > 10 )
		{
			UE_LOG( LogNetTraffic, Log, TEXT( "High single frame packet loss. PacketsLost: %i %s" ), PacketsLost, *Describe() );
		}

		InPacketsLost += PacketsLost;
		Driver->InPacketsLost += PacketsLost;
		InPacketId = PacketId;
	}
	else
	{
		Driver->InOutOfOrderPackets++;
		// Protect against replay attacks
		// We already protect against this for reliable bunches, and unreliable properties
		// The only bunch we would process would be unreliable RPC's, which could allow for replay attacks
		// So rather than add individual protection for unreliable RPC's as well, just kill it at the source, 
		// which protects everything in one fell swoop
		return;
	}

....
}

I Found code in engine like above, which indexed all packet it got, and discarded any one not smaller. I think the conclusion is: unreliable rpc guarantees: one call in source triggers only one(no more than one) execution in remote, and two calls on same actor in source triggers only two(no more than two) executions in remote(and the two executions may lost, but always in same order as they are called in source if they all arrived remote ).

Epic, could u give a confirm to my conclusion?

hello, Kyle
I have found a bit more about unreliable RPC, could u confirm my conclusion in the post?

Also found the line calculate packet id

	const int32 PacketId = InternalAck ? InPacketId + 1 : MakeRelative(Reader.ReadInt(MAX_PACKETID),InPacketId,MAX_PACKETID);

the MakeReleative() call seems wield to me, wouldn’t this cause incorrect checking of packet validation? For example,
Reader.ReadInt(MAX_PACKETID) = 0, inPacketId = 57345, then the PacketId will be 57345 + 8191. And following logic will accept this packet, is this expected behavior?

Also this code seems leaved a door open to let older packet to be considered correct one if some case(MakeRelative() can returns same value with different value of parameter one)

You can never rely on when RPC’s will be sent. You can use rep notify events to know when a replicated variable has reached client(s) but you can never tell when that will happen. I would not rely on a system which relies on when client(s) will receive RPC calls from the server.

As an example, if you were to replicate something every 1 second from the server down to the clients but the clients were say 50ms, 100ms, and 500ms ping away from the server. It would take at least 50ms to reach the first, 100ms to reach the second, and 500ms to reach the last. This means the last client would be a minimum of 1/2 second delayed from when the server sent down a RPC call. When you factor in all the other portions that are also replicating, there is no way to tell in what order your RPC call will reach the client(s) as the server is going to be sending a lot of information at a very regular time, with different priority levels.