Starting multiple server instances on different ports is a viable approach, though unfortunately it does require dipping into C++ code (I don’t know of a way to launch additional server instances directly from blueprints). Here is a resource that I found helpful for running the server executable (and keeping track of their process IDs to shut them down later). I passed the server executable path and arguments into my function as FString parameters, then converted them to TCHAR* so that I could use them with CreateProc.
The arguments parameter should be anything you’d put into the command line (or Windows shortcut) for launching the server. In this case, we’ll need to include the port (“-port=7778”). You could also include the “-log” flag so that a console window appears for the server instance. This tends to be helpful during the early stages of development, but you might want to remove the tag later on.
Once you have a server instance running, you can tell clients to connect to it. To do that, just use the “OpenLevel” blueprint node, passing in your server’s IP address and the port number separated by a colon (127.0.0.1:7778). After all of the players have connected, the server instance can run ServerTravel (using the name of the map you want to load) to start the game.
The last trick for you is going to be figuring out how to manage your actual matchmaking. You might need a persistent server that everyone connects to which redirects players into server instances appropriately. The persistent server should be able to keep track of all of the instance by port number (so that it can send players to the right “rooms”). As games finish up, you can reconnect players to the persistent server so that they can be reentered into matchmaking. And of course, you’ll probably want to have each server instance keep track of how many players are still connected so that it can shut itself down when everyone leaves.
Hope that helps!