Approaching online multiplayer

I am wrapping up a course on Udemy on Unreal 4 and the next thing I want to look at is multiplayer. Not interested in doing a full robust multiplayer game as a project, but I want to I understand how it works and make a simple example or two. Now I have seen examples but they all work with OnlineSubSystem = Null or Steam. Null means it is LAN only and that’s not what I am looking for and Steam requires an AppId and all players to be logged into steam as they play. There is a demo AppId but even for just my friends to have to log into Steam and look like they are playing “SpaceWar” to try out anything that seems like a weird limitation.
I hear about other options like GameLift, GameSpark, Photon, and others. Are these alternative online subsystems? Are they different flavors of the same thing? Are they supposed to replace Steamworks API? I basically want to build a dedicated server project for my game, have it sit somewhere in some cloud service that I pay some amount for hosting, and when clients want to play it hits this cloud service and starts an instance of this game or joins one in progress for a match of Deathmatch or something like that. Is that what these services do? Or are they providing social features, cloud saving, analytics, and other side services which I am not that interested in.

Does anyone have any recommendations on what I should look at or where to start? I feel like I am missing something fundamental, not about client-server model and replication concepts, but more like services and hosting. Thanks.

I haven’t done any dedicated server stuff but here is some documentation with a quick google search:

Hope some of this helps!!

GameLift, GameSpark, Photon, Playfab are all alternatives to used UE4 dedicated servers (in the case of Gamesparks and Photon you can use their services in addition to dedicated servers but also without e.g. Gamesparks realtime).

it is also possible to use one of the clients as the serve (but its generally not recommended due to extra load on that one client + it becomes the most obvious place to hack a game)

Thanks for the replies. I have been doing more digging on my own. Apparently for my situation one option is to set OnlineSubSystem to Null and then have a separate master server that keeps track of listen server IPs. Then ever client who starts a listen server session would send their IP to this so other clients could find them.

But then there’s another problem. Apparently clients behind a router will have a NAT mask their IP and port being used. So I have to do something called NAT punchthrough? Does anyone know anything about this or have a good example?

OK I found this article

This looks like it’s really old but hopefully it still works this way.
Which goes over what NAT punch-through is and now I am trying to reason out how it would work in an Unreal 4 listen server situation.

The gist is that if your client is sitting behind some kind of NAT(and it’s 2017 so of course they are) then they cannot be sent packets directly from any server. A client on a NAT has an internal IP that only the NAT knows about. When it wants to talk to a server in the outside world, the NAT makes up an IP for it to communicate with. So if your internal IP is your external one might be on port 1040(I don’t know if either of those are special or reserved I made them up randomly). And what that results in, is if that server wants to send data to this client, that client needs to establish that internal/external IP thing first. Otherwise the server has no IP to connect to.

This is how I am thinking this will work:
What you do is have a separate login-like server that on startup of the game. Then this login server has a list of IPs of all current players. This way when your client wants to start a listen server, the login server will flag it’s IP as one that can be connected to as a server with an active session. When a different client finds this server in a list of active sessions, which comes from this login server, it will connect using the same IP it “logged in” with. The listen server will see it’s getting a request sent to the IP it logged into, and the listen server’s NAT will be able to resolve that correctly. Also now that it has gotten this first request, it also has a valid IP to send data to, so it’s NAT will resolve it’s IP correctly.

It would be pretty simple for me to make a login server to hold these NAT-external IPs in node.js and then have a simple time-out system for removal or something. I understand that there are “stricter” NATs, NATs whose firewalls will not allow packets sent through ports not on a small whitelist of allowed ports, even if a connection to the same server on a different port has been previously made. So if someone’s NAT does not like the ports that Unreal uses for it’s in game networking I am screwed anyway and that’s something all games deal with. At that point the user must be asked to punch holes in their own firewall or I have to guess at ports until one is found that works and save it for this IP.

Can anyone verify that this makes sense? Do I understand this correctly or am I way off base? What big important details am I missing?