Jump to content
  • Advertisement
Sign in to follow this  
pindrought

listen, accept and port determination (TCP)

Recommended Posts

I originally thought that when listening on a port, that all accepted connections would be on their own unique local ports.

 

However, recently I was reading someone say that this isn't necessarily the case and the only thing unique was the ip+port combination.

 

This got me wondering - is it possible that when you accept a new connection, that the local port assigned for that socket to use is the same as the port being used to accept new connections?

Also, is it possible that two new connections would be accepted that are using the same local port (but different endpoint ips)?

 

Thanks

Share this post


Link to post
Share on other sites
Advertisement

 

2 hours ago, pindrought said:

However, recently I was reading someone say that this isn't necessarily the case and the only thing unique was the ip+port combination.

It is the source, and destination port+IP.

2 hours ago, pindrought said:

This got me wondering - is it possible that when you accept a new connection, that the local port assigned for that socket to use is the same as the port being used to accept new connections?

It actually always does, and this is part of how the client computer, and any firewalls, NAT routers, etc. identify the packets as being for that connection. You can see this in packet capture tools like say Wireshark.

You will see the first packet of a TCP connection from the client have a random ephemeral port (or dynamic. Usually from a pool somewhere around 32768 to 65535 for modern OS) to the intended server port (e.g. 80 for HTTP or 443 for HTTPS) . The response packets then use the same port numbers in reverse (e.g. from 80 or 443 to that random port).

2 hours ago, pindrought said:

Also, is it possible that two new connections would be accepted that are using the same local port (but different endpoint ips)?

Yes, but either at different times, or the destination (client) port will be different.

Share this post


Link to post
Share on other sites

A TCP connection is uniquely identified by the five-tuple (global-time, source-ip, source-port, destination-ip, destination-port)

If you only consider a particular point in time, you're left with the four-tuple (source-ip, source-port, destination-ip, destination-port)

When a client connects to host:port, that fixes the destination-ip and destination-port, These do not change when the server accepts the incoming connection -- the connection will always have (destination-ip, destination-port) as part of the tuple.

Given that the source client has a given IP address, that fixes the source-ip part of the tuple, which only leaves the source-port as the variable part to tell apart multiple connections to the same target:port from that same source host. This is why the connect() call allocates a "random, unused" port number for the client-side socket when connecting, and then keeps that for the duration of the connection.

If you are in a datacenter, and generate a lot of connections from the same source host to the same target host (for example, for an internal HTTP service, or database connection without connection pooling,) then it's possible that you use all source ports on the client machine for the given target host:port. Different OS-es use between 16k and 64k space for these "ephemeral" ports, and a port cannot be re-used within two minutes of the connection ending, because of the TCP spec. This is because a "late packet" from a previously connection should not be confused with a packet for an existing connection between the two hosts. So, the maximum sustained number of connections made and finished between two hosts is somewhere between 136 and 546 connections per second. If this ends up being a problem for you, the first thing to do is probably to turn on connection pooling or something similar; if you can't do that for some reason (looking at you, Ruby and PHP,) then you may need to create more IP addresses for the same host on the same physical interface, using interface aliases, and round-robin outgoing connections across these interface aliases. Here's hoping your game will be so successful that you'll have to worry about this 🙂

 

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!