question

Linus Neuman avatar image
Linus Neuman asked

Question regarding ServerListeningPort and ClientConnectionPort in GSDK for UE4

Hi,

I have a Windows container build in Playfab set up where the UnrealServerGsdkHostPort is set to 56100.

I assumed this would be overridden to whatever value the server instance gets allocated when getting initialized.

However, the port is never overridden and is kept at 56100.

Example log:


[2022.03.24-13.16.46:036][ 0]LogPlayFabGSDK: Warning: GSDK Game server listening port: 56100
[2022.03.24-13.16.46:036][ 0]LogPlayFabGSDK: Warning: GSDK Game client connection port: 30000
[2022.03.24-13.16.46:036][ 0]LogPlayFabGSDK: Warning: Assigning Unreal Server Host Port to MPS port: 56100

Here, the server instance gets the connection port 30000 allocated from Playfab.

But it is not used in GSDK to override the connecting port, instead we use the game server listening port 56100.

As a result, the session gets hosted on port 56100, and if you try to connect, it simply fails since that is not the actual port that is opened to the instance. Another result is that multiple servers with the same IP and Port show up in our backend session list (EOS).

Is this intended, or are these variables mixed up?

if (GamePorts.Name == TEXT("UnrealServerGsdkHostPort")) {
   UE_LOG(LogPlayFabGSDK, Warning, TEXT("GSDK Game server listening port: %d"), GamePorts.ServerListeningPort);
   UE_LOG(LogPlayFabGSDK, Warning, TEXT("GSDK Game client connection port: %d"), GamePorts.ClientConnectionPort);
   UnrealServerGsdkHostPort = GamePorts.ServerListeningPort;
   break;
}

The comments are a bit confusing:

/// <summary>
/// The port at which the game server should listen on (maps externally to <see cref="m_clientConnectionPort" />).
/// For process based servers, this is determined by Control Plane, based on the ports available on the VM.
/// For containers, this is specified by the game developer in the Build configuration.
/// </summary>
UPROPERTY(BlueprintReadOnly)
int32 ServerListeningPort = 0;

/// <summary>
/// The public port to which clients should connect (maps internally to <see cref="m_serverListeningPort" />).
/// </summary>
UPROPERTY(BlueprintReadOnly)
int32 ClientConnectionPort = 0;

The comment for ClientConnectionPort says "see cref="m_serverListeningPort" and vice versa.
Is this code bugged and actually supposed to be the other way around?

I am also a bit unsure of the difference between these variables, even after reading around here and there from where I can find information about these variables.
My suspicion is that the GSDK code assumes that both of these variables will have the same value, and therefore just picking one of them to represent the bound port, but I might be completely wrong there.

If I swap the code around, it properly binds to the overridden port instead, but client won't connect.

Cheers,
Linus

multiplayergame manager
10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

1 Answer

·
Dimitris-Ilias Gkanatsios avatar image
Dimitris-Ilias Gkanatsios answered

First of all, have you tried working with LocalMultiplayerAgent? PlayFab/MpsAgent: Azure PlayFab Multiplayer Servers LocalMultiplayerAgent project and helper libraries (github.com). This will save you time as you're debugging locally.

The GSDK tries to find the port called and create the game server to listen to this port gsdk/GSDKUtils.cpp at b66032a670a9dc69ef27874b5e91587653ac78f7 PlayFab/gsdk (github.com)

The terminology is correct - the ServerListeningPort is the port that the server process will listen to, the ClientConnectionPort is the Port that will be open in the external Load Balancer and clients will connect to. Be aware that since you are using containers, the port 56100 is open only in the network namespace of the container. It's not exposed outside. Docker will do the mapping that traffic to port 30000 will be forwarded to port 56100.

The comments are also correct - the clientConnectionPort maps to serverListeningPort (i.e. traffic coming to clientConnectionPort is forwarded to serverListeningPort).

Check this video around minute 21 to learn more about how we map ports on the cloud. (3) PlayFab Multiplayer Hosted Servers part 1: Multiplayer Servers Quick Start - YouTube

Moreover, since each port 56100 is opened in each container network namespace, it's perfectly legitimate to have multiple containers, each one listening to port 56100, since this port is mapped to another one in the host network namespace. This is different than running game servers in process mode, where all processes are in the same (host) network namespace, so they have *different* port numbers, to avoid collision.

Apologies for the confusion, this is how Docker works. We're constantly working to improve the experiece though, don't hesitate to challenge us to do better!

5 comments
10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Linus Neuman avatar image Linus Neuman commented ·

Hi,

Thanks for the explanation!
I have used the local agent where it doesn't work either.

I believe I see where the issue is now.

Since you host the server to the bound port 56100 according to my configuration, and then the server managing the container forwards the correct port, whether it be 30000, or 30001, to the correct container and its port 56100.

However, the problematic behaviour here is that since GSDK is telling UE4 that the bound port is 56100, it's going to forward this port to the Online Session. Which means that when matchmaking, the port that the client tries to connect to is 56100, not 30000 which is the external port.

All examples I can see that are available, all rely on the game client manually connecting to the correct external port, which of course works fine, but I believe that none of this works as intended when using the session interface?

I have to manually inject the GSDK external port to the session info, and use that when connecting instead, since by default, the bound port is what gets forwarded to the client when connecting.

Cheers!
Linus

0 Likes 0 ·
Dimitris-Ilias Gkanatsios avatar image Dimitris-Ilias Gkanatsios Linus Neuman commented ·

Happy that things are clearing out. The IP:Port information that you get when you use the RequestMultiplayerServer API should be the ports that the client needs, in order to connect. Doesn't this work for you?

0 Likes 0 ·
Linus Neuman avatar image Linus Neuman Dimitris-Ilias Gkanatsios commented ·

Hi! That might solve the case, but we use matchmaking on EOS to connect which actually doesn't communicate at all with Playfab. Currently we request servers manually on the web interface which is not ideal.

0 Likes 0 ·
Show more comments
Dimitris-Ilias Gkanatsios avatar image Dimitris-Ilias Gkanatsios Linus Neuman commented ·

Also, weird that it doesn't work with LocalMultiplayerAgent. Are you connecting to the NodePort?

0 Likes 0 ·

Write an Answer

Hint: Notify or tag a user in this post by typing @username.

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.