Client cant join a server if server is running reliable rpc

To reproduce this:

Client can join:

-Create a new project using THIRD PERSON BP template project

-Open level blueprint

-Add a custom event, set replication property to multicast, DONT CHECK RELIABLE yet

-Call custom event on event Tick in level blueprint

Simply like this


-Launch game with 2 clients, it work

now to reproduce bug so client cant join:

-Check RELIABLE property on custom event

Is that even a bug or is it normal? if it isnt a bug how a client can join a game if server is running a game with reliable rpc running on it ?

Hey skeleton60,

I am sorry this post was not addressed earlier. I was able to reproduce this behavior in 4.5.1 and have entered a bug report for our developers (UE-4901). I will let you know when I see an update. Thanks for report!

Hi ,

how is progress? There are similar issues with reliable multicasts in 4.6.1. Multicast RPC Issue [Update 8/12] - Programming & Scripting - Epic Developer Community Forums

I’ve been digging through source with 4.6.1. Your main issue here is that you are calling a reliable multicast on tick event. Multicasts are designed for non gameplay important events and should remain unreliable. When made reliable, call to client is “forced”. If reliable multicast rpc is called before client is done logging in, because it is “forced”, it thinks it is a broken or new instance of a previous connection.

Engine\Source\Runtime\Engine\Private\NetConnection.cpp

// on  server, if we receive bunch data for a channel that doesn't exist while we're still logging in,
// it's either a broken client or a new instance of a previous connection,
// so reject it
else if ( PlayerController == NULL && Driver->ClientConnections.Contains( this ) )
{
    UE_LOG( LogNetTraffic, Error, TEXT( "UNetConnection::ReceivedPacket: Received non-control bunch during login process" ) );
    Close();
    return;
}

I came up with a fix but requires editing engine source.

change \Engine\Source\Runtime\Online\OnlineSubsystemUtils\Private\IpNetDriver.cpp at line 320 from

if (IsRelevant)
{
	if (Connection->GetUChildConnection() != NULL)
	{
		Connection = ((UChildConnection*)Connection)->Parent;
	}
						
	InternalProcessRemoteFunction( Actor, SubObject, Connection, Function, Parameters, OutParms, Stack, bIsServer );
}

to

if (IsRelevant && (Function->FunctionFlags & FUNC_NetReliable) ? Connection->OwningActor != NULL : true)
{
	if (Connection->GetUChildConnection() != NULL)
	{
		Connection = ((UChildConnection*)Connection)->Parent;
	}
						
	InternalProcessRemoteFunction( Actor, SubObject, Connection, Function, Parameters, OutParms, Stack, bIsServer );
}

Now, if multicast is unreliable, it behave as before. But if it is reliable, it won’t be called on client until Connections owning actor is not null. In this case, I believe that owning actor needs to be a player controller or else connection will still be closed.

Another option that doesn’t involve changing source code is to not use reliable multicasts until after all clients have connected to host. If that is not an option, use reliable multicasts sparingly and it should be a very rare occasion that connection is dropped when client tries to join.

In our latest main branch I’ve changed functionality so that if a connection has no viewer (no PC or associated owning actor yet) it will not receive multicasts, whether reliable or not. reasoning for this is:

  • Game code has no reasonable way to know if all clients have connected, and for a join in progress scenario has no way to send a multicast RPC to a select number of clients. Basically: game code cant work around this.
  • RPC will almost never be able to be handled on other end.

fix is straight forward. I don’t think it will be in 4.7 though. You will need to add it manually until then. ProcessRemoteFunction looks like this:

	// Multicast functions go to every client
			TArray<UNetConnection*> UniqueRealConnections;
			for (int32 i=0; i<ClientConnections.Num(); ++i)
			{
				Connection = ClientConnections[i];
				if (Connection && Connection->Viewer)
				{

(Adding check to Connection && Connection->Viewer is what is important).

A side note!

You may want to rethink your approach if you are sending a multicast RPC in every tick. This sounds to me like you are replicating state via events. If you have some state that is constantly updating, you should replicate it via a replicated property and let replication system handle sending it to everyone. RPCs should be used to replicate events. Properties should be used to replicate state.

Hi -
So is it safe to use reliable, multicast functions for actors that may go out of relevancy for some clients?
following comment in IpNetDriver.cpp suggests otherwise:
// Multicast reliables should probably never be used in gameplay code for actors that have relevancy checks.

What’s appropriate way to handle things that should behave as reliable if relevant? Think of an open world game where clients can come and go all time. AI running on server frequently needs to notify all clients to play various one-off anims (ie: a telegraph on an incoming attack from an AI).

I’m ok with reliable, multicasts getting dropped on floor for clients who do not have actor relevant. My concern is that this doesn’t cause other bad behavior, such as client disconnecting.

Thanks,
-Josh

In AI example I would suggest that just be an unreliable message if animations are short, or if they are long potentially replicated as state (properties), e.g, ‘current animation + time started/left’ since all you care about is last played animation. This would also make it so if an actor suddenly became relevant then it would know what animation should be playing.

Reliable really implies event is critical for actor to function. It also implies ordering is important (if event A is dropped then event B may not be able to be handled properly).

I don’t get it, how do I tell my character to do something across network, if I don’t use Reliable NetMulticast then?

I have exactly what said here → “Reliable really implies event is critical for actor to function. It also implies ordering is important (if event A is dropped then event B may not be able to be handled properly).”

SO what then?

Huh, you confused me even more. Does Reliable NetMulticast re-fire all those A-B events for those who join later?

Well, anyhow my problem is, there’s a fatal error when clients try to rejoin a game with many NetMulticast firing. game simply just crashes on occations. I tried switching to unreliable, and problem still persist. I then tried pausing game with new user’s Prelogin() and unpause it afterward, but that doesn’t help either.

Is there a better way to do this?

If you have that exact scenario, then by all means use reliable multicast. I don’t mean to say you never ever should use them, but cases should rare in my experience.

short answer is, usually if something is important it should probably be replicated as state (a replicated property). These are guaranteed to make it to clients and anyone who joins late will get latest values.

Consider if you had events A → B → C, and all are critical and must be processed in order. You could replicate those events as reliable RPCs and network layer will get them to everyone - everyone that is currently in game and is relevant to those actors! If someone joins in progress between events A and B, he will never know about event A. If knowing about A was truly critical for actor to work, then you are in trouble.

If you had those events A B C, ask why are they critical? If they are critical, they probably have side effects. Can you replicate those side effects directly instead? Say event A sets a bool that will influence how event B and C work (maybe if event X happens before B, then C acts differently). Instead of replicating A as an event, replicate bool that A sets as a property. example is primitive, but that is point I was trying to make. Don’t confuse critical with “important”. When I mean critical I mean " event does something that if everyone doesn’t do it actor will not be able to recover/function properly"

Huh, you confused me even more. Does Reliable NetMulticast re-fire all those A-B events for those who join later?

Net multicast does NOT refire if people join later.

Without knowing more about your problem, if you think you have to fire multicasts nearly every frame, you should probably be using replicated properties instead.

You should post your crash in another thread and someone on network team can fix it or figure out what is going on.

i heard on a tutorial that RELIABLE check box is only there if you want event to ALWAYS be called…no matter how much stress is on your network.

UNRELIABLE means that if your network has very little stress then yes event will be called but if your network is copping a beating then it will call event sometimes and sometimes it wont.

So only use RELIABLE when event MUST be called. BUT you shouldnt be using event ticks for most things. Clients coming and going should be handled a different way rather than an event tick to see if someone joined.

Hi ,

I was linked here from this:

What I’m seeing is reliable multicasts get dropped when a client is paused in debugger for 10-20 seconds or so, but not paused long enough to cause a client timeout with disconnect. Is that normal? I need events to be reliable, and would rather a client get dropped than have gaps in reliable multicast events.

For anyone Googling broken reliable multicast and trying to decipher UE-24772, I’ve found origin of 1.5s timeout it refers to:

in int32 UNetDriver::ServerReplicateActors_PrepConnections:

        if ( OwningActor != NULL && Connection->State == USOCK_Open && ( Connection->Driver->Time - Connection->LastReceiveTime < 1.5f ) )
        {
        [...]
        }
        else
        {
                    Connection->ViewTarget = NULL;
        }

Once it sets Connection->ViewTarget to NULL, that’s what breaks ProcessRemoteFunction.

A 1.5s timeout seems really short for this, if I’m reading this right, someone could get a burst of packet loss or have their machine hitch for that amount of time, and they would start losing reliable multicast packets?