Advertisement

Question About Port assignments

Started by March 13, 2015 06:41 AM
14 comments, last by hplus0603 9 years, 8 months ago

Hi.

Is it ok to use any port number, Dumb ass me set my server to listen on port 7777

and only assigned port 7777 to the router, thats ok the clients can connect to it but then the clients can't create a room on the server

if it uses port 7777 to create a new room all net work messages just go to the server.

Help from google say's user should use ports from 49152 to 65535 doe this matter.???

So I came up with this class to reuse ports

.


//-----------------------------------------------------------------------------------------------
//this class will hold our available port number
//we can't assign the same port to a room that is all ready in proccess
//using ranges from 49152 to 65535
//------------------------------------------------------------------------------------------------
class cAvailablePorts
{
public:
	cAvailablePorts()
	{
		int32_t startrange = 49152;

		while(startrange < 65535)
		{
			PortNumbers[startrange] = false;//a free port
			startrange++;
		}

	}
	~cAvailablePorts(){}


	//--------------------------------------------------------------------
	//returns a port if -1 then there is no ports left to create a room 
	//--------------------------------------------------------------------
	int32_t GetPort()
	{
		//we need find the room the client is in and delete it as well
		for(PortNumbersIT = PortNumbers.begin(); PortNumbersIT != PortNumbers.end(); ++PortNumbersIT)
		{
			if(PortNumbersIT->second == false)
			{
				PortNumbersIT->second = true;//set in use
				return PortNumbersIT->first;
			}
		}

		return -1;//error we must have some good game hehehe
	}//end getport
	///////////////////////////////////////////////////////////////////////


	//----------------------------------------------------------------------
	//when we close a room we need to reclaim the port
	//----------------------------------------------------------------------
	void RecliamPort(int32_t port)
	{
		PortNumbersIT = PortNumbers.find(port);
		if(PortNumbersIT != PortNumbers.end())
		{
			PortNumbersIT->second = false;//flag as not used

		}

	}//end RecliamPort
	////////////////////////////////////////////////////////////////////////



	//holds our port and a flag if in use
	std::unordered_map<int32_t, bool> PortNumbers;
	std::unordered_map<int32_t, bool>::iterator PortNumbersIT;

};//end class cAvailablePorts
////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////



That assigns ports to clients rooms they create on the server. Each room needs its own port.

But now comes the router issue I've now assigned port ranges from 7777 to 65535.

should I just move the server port to 49152 and start the reuse ports from 49153 to 65535.

or is it ok to leave it. Whats the correct practise.

I have it on line if anyone would like to test it. I'm hosting it on my lap top with a dns from noIP.com works great.

link

There's a bunch of known protocols (and a nice wiki page with a lot of them). As long as your base server address doesn't overlap with anything you think your users will be using, it makes for an ok default port. But you should probably make it configurable, so that individuals hosting the server could change it later.

As to your port-cycling code, it's likely going to need to be more robust than what you have. Other processes (like your browser) are free to open up ports in that same range. But you don't really need any of that logic you wrote. To quote MSDN's bind documentation for a socket "For TCP/IP, if the port is specified as zero, the service provider assigns a unique port to the application from the dynamic client port range.". That is going to be far more reliable, than using your own tracking for the port number. You can always retrieve the port number that a socket got bound to.

Advertisement
But how do I port forward the router with random ports it needs a range. Do I just set the range to 0 to max range. Is that some thing you would do.
Is it a problem if you assign in the router all the ports
... 0 to max range ...

Re-read the documentation I linked. Putting in 0 causes it to pick within the range [49152, 65535)

Even if you used your current code, you'd still need to port forward the exact same port range [49152, 65535), so you're in the same situation.

UPnP is one option to get around manually port-forwarding. Your program can ask the router to temporarily port-forward which-ever port it opens.

Whomever is hosting always has the option to use DMZ mode on their router (effectively "port forward everything")

The only way to shrink the size of the manually added port-forward, it to use a smaller manually picked range. To do that you'd need to use something similar to your code, but on a much smaller port range (eg only 99 rooms from [50001, 50100)). But if you go with manually choosing, for each port number you manually choose, you still have to attempt to open a socket on that port (which may fail due to it already being open by another program), so your process of marking ports used/unused needs to also have a state for temporarially-in-use-by-other-program.

Ah that's is what UpnP option in the router is for. That would explain how it was working on the local net work with just 7777 assigned to the server port.

I think I get it now all I need to do is assign the server app port
A port number(user assigned) set UpnP on the router. Then when a client wants to create a room use 0 for the port then connect and pass on that port to the client for them to connect to the room. Thats a Job for tomorrow.
If you are running a server, you pick a port number, traditionally in the 2048-9999 range (because 1-2048 is already taken by everything else and may require root to bind to on some OS-es,) and bind to that port. You make sure that port goes from your public IP address to your server (which may include port forwarding in a home networking environment.) You must pick a fixed port, else the clients won't know where to connect to (unless you build a whole complex service discovery system, which you don't want to do.)

If you are running a client, you call connect(), which will let the OS pick any unused port on the machine (typically in the 48k-64k range but this varies) and you really don't need to care which port it chooses, because what matters is the server/service port it connects to on the other end. The NAT in the firewall/router will make sure that the locally picked port used in connect() gets the return address from the server.

If you are running a server, and something else is already listening on the port number you've chosen, your server will not be able to bind to the port, and should blow up. This is also a good safeguard against running two copies of the server on the same machine. Let the server operator know what's going on, and fix it -- this is not something the software itself can fix. It's also a very rare kind of misconfiguration.
enum Bool { True, False, FileNotFound };
Advertisement

and only assigned port 7777 to the router, thats ok the clients can connect to it but then the clients can't create a room on the server


I don't understand this. Why does a 'room' require a whole new port? Among other problems, that puts a hard limit on how many rooms you can possibly support, which also means you're susceptible to a form of Denial-of-Service attack if a client decides to create a bunch of empty rooms.

If you have a dedicated server, there should be a very small number of fixed, permanent ports. In the simple case, just one port suffices; clients connect to that one port and all communication to other services/backends forward through that frontend service they originally connected to.

Sean Middleditch – Game Systems Engineer – Join my team!

Why does a 'room' require a whole new port?


This is a good question, that I agree with! The only reason to listen on a different port on the same machine is if you're having a different service/process entirely running.
enum Bool { True, False, FileNotFound };

Sorry about the late reply, got roped into helping the brother inlaw take out his HQ engine

fun fun.

This is how the server works.

The goal was to have persistent room's hosted on the server

By persistent, when the last client leaves the room, the room will set a timer and self

monitor, when the time has reach a threshold it will remove the room.(that should take

care of freaks who spam rooms creation).

All Room will have a identifier assigned. For the chat this is just the room name

but if this was a game it would be its map, the map is created in a editor that

when saved creates a id also used as version number(For sending updated maps later story).

if a room has the same type this means it's allready active on the server and the creating

client will just be told by the server to join it.

When a client initiates a request to the server to create a new room. It first check to

see if a room exists if not it creates a listening socket, it then sends the accept back

to the client with the port number(I did send the IP of the server but that turns out to

be the local networks IP. I have removed and fixed this).

The client then recieves this message if not its a lost connection, then with the sent port

attempt to connect using the correct IP.

The room is now waiting for the clients response that holds the name of the client and

anything else that maybe needed. Once the room recieves this data it sends current clients

list to all clients.

my reason was to have each room control all connected clients to the room

and this allowed for processing the game server side. Each room would need to process the

game logic. I can't see that using one port controlling all login and disconnects and processing

all rooms and game logic even working, also the design help in haveing each room its own message

handler that cut down on the amount of case statements in the message proc recieved from the network

layer, My first try was the other way it worked but this is the improved version. So far I'm

glad I changed it.

I'm implementing the auto port numbering mentioned above pass 0 to bind.

I'll get it in a working state and see if it is something. I've only been at it for 5 weeks give or take.

And I had so much to learn in fact 5 weeks went fast. I actually really enjoyed it, it was like it renewed

my love for programming, maybe because I've been working on the same app for 8 years and this was a change.

I learnt about boost, GoogleProtocol, refresher on multi threading, boost::bimaps(very cool, once you get

your head around it) lockfree queue's never new dooms port was 666(woooo), and setting up server assigning

static ports, port forwarding and the rest I think I have forgotten.

And thank all for your time and patient. Any advice on the above is fine.

I guess if you're using UDP there might be a slight advantage to doing multiple server ports like this, but with all the complex code and hassle involved in port forwarding and the security implications involved in opening up all your ports on your firewall, it doesn't sound worth it over having a single port that hands off an accepted TCP connection to the room. On Linux you can even pass open socket file descriptors to separate processes over IPC if you've partitioned your server that way (dunno what platform your server is running on).

Stephen M. Webb
Professional Free Software Developer

This topic is closed to new replies.

Advertisement