Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Distinguishing multiple clients with the same IP using UDP  (Read 9420 times)

0 Members and 2 Guests are viewing this topic.

Wizzard

  • Full Member
  • ***
  • Posts: 213
    • View Profile
Distinguishing multiple clients with the same IP using UDP
« on: April 07, 2011, 05:59:49 am »
As far as I can see, the only way to distinguish multiple clients with the same IP using UDP is for each client to have a unique port. If you bind two clients with the same IP to the same port, you get random behavior determining which client gets packets. The problem is that I don't have a way of guaranteeing each individual process that is ran under the same IP receives a unique port.

It seems that Winsock already has a partial answer to this problem:
Quote
Binding to a specific port number other than port 0 is discouraged for client applications, since there is a danger of conflicting with another socket already using that port number on the local computer.

Source: http://msdn.microsoft.com/en-us/library/ms737550

The above may only apply to a single computer running on the same IP whereas I need unique ports for all computers using the same IP.

UPnP is quite a mystery to me, but it may have the true answer to this problem. So, I'll be checking out the MiniUPnP library referenced here.

Conclusively, I just need two instances of the same application running on the same IP to be guaranteed to be able to receive packets. Is there a way to do this in SFML?

Edit:
After posting, I realized that I can use a temporary port to request a unique port from the server. With the unique port that the server gives, I can rebind the client to a permanent port.

However, this is just a hack. Two clients on the same IP will not be able to connect at the same time because the temporary port is the same.

danman

  • Hero Member
  • *****
  • Posts: 1121
    • View Profile
    • Email
Distinguishing multiple clients with the same IP using UDP
« Reply #1 on: April 07, 2011, 07:03:42 am »
You just have to bind an udp socket in the client, and always send message with him, he will send message in a different port than the other one.

Or you can send a "client ID" with udp packets.
Pointilleur professionnel

Wizzard

  • Full Member
  • ***
  • Posts: 213
    • View Profile
Distinguishing multiple clients with the same IP using UDP
« Reply #2 on: April 07, 2011, 07:58:43 am »
Quote from: "danman"
You just have to bind an udp socket in the client, and always send message with him, he will send message in a different port than the other one.

Or you can send a "client ID" with udp packets.

If I bind two UDP sockets using the same IP to the same port, only one of the sockets will receive packets. I don't know how to ensure that the clients will send packets on different ports than other clients of the same IP. A client ID would be fine if all the clients received all the packets, but only one socket is receiving packets.

Edit:
Upon further inspection of UPnP, it seems it's not an answer to this problem.

Tank

  • SFML Team
  • Hero Member
  • *****
  • Posts: 1486
    • View Profile
    • Blog
    • Email
Distinguishing multiple clients with the same IP using UDP
« Reply #3 on: April 07, 2011, 12:46:28 pm »
Exactly, UPnP establishes a required tunnel between two endpoints. Mainly used for local ports that are about to receive data (instead of first sending data, where NAT applies).

Normally, with average router hardware ;), you shouldn't get problems using the same port on two or more machines behind a router. The router should take care of that in its translation table. When it sees that there're two identical ports used, it should translate one of the two to another port number for packets being send through the internet.

Have you actually tested it? Did it have strange behaviour?

You could do a simple handshake so that a client can make sure that the socket is properly setup:

- Bind your UDP socket.
- Send a packet to the server containing a random number (preferably a hash that's somehow dependant on time and maybe the machine's name to avoid clashes).
- Server answers with the same hash.
- If client receives it below a timeout value, everything's okay, otherwise bind to another port.

Why are you binding your local sockets to specific ports anyway? Normally the OS takes care of choosing the port number so that chances are fairly low that you get a port number another machine on your network already uses. (this, of course, only counts for sockets on the client side, sockets on the server side have to be bind to a specific port, otherwise clients don't know where to send to ;))

Wizzard

  • Full Member
  • ***
  • Posts: 213
    • View Profile
Distinguishing multiple clients with the same IP using UDP
« Reply #4 on: April 08, 2011, 01:49:53 am »
Quote from: "Tank"
Normally, with average router hardware, you shouldn't get problems using the same port on two or more machines behind a router. The router should take care of that in its translation table. When it sees that there're two identical ports used, it should translate one of the two to another port number for packets being send through the internet.

Have you actually tested it? Did it have strange behaviour?

Alright! I just spent the last 15 minutes testing to see if my desktop and laptop can both connect simultaneously and it works fine. The router does it's job and ensures that the clients on two different machines using the same port get access to the server.

So, the problem I'm having is isolating a single client on a single machine to a unique port.
Quote from: "Tank"
You could do a simple handshake so that a client can make sure that the socket is properly setup:

- Bind your UDP socket.
- Send a packet to the server containing a random number (preferably a hash that's somehow dependant on time and maybe the machine's name to avoid clashes).
- Server answers with the same hash.
- If client receives it below a timeout value, everything's okay, otherwise bind to another port.

This isn't safe because binding a port to the same port as another application sometimes blocks the previous application from receiving data. Who's who seems random on my desktop, but not all of the applications on a single port will be guaranteed to receive packets. Running additional clients shouldn't affect other clients' integrity. Although, it is possible to hack around this instability with timeouts and port changing when pinging the server from my main loop.
Quote from: "Tank"
Why are you binding your local sockets to specific ports anyway? Normally the OS takes care of choosing the port number so that chances are fairly low that you get a port number another machine on your network already uses. (this, of course, only counts for sockets on the client side, sockets on the server side have to be bind to a specific port, otherwise clients don't know where to send to)

The SFML SocketUDP implementation does not allow sockets to call the Receive member function before a call to Bind. So, even though Windows implicitly binds the socket when I make a call to Send without first calling Bind, SFML does not allow me to Receive unless I first explicitly make a call to Bind with a port. SFML also does not recognize that the port is set by Windows during a call to Send through it's GetPort member function. Basically, SFML offers me no way to use the OS-assigned port to receive packets.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Distinguishing multiple clients with the same IP using UDP
« Reply #5 on: April 08, 2011, 08:05:53 am »
Quote
The SFML SocketUDP implementation does not allow sockets to call the Receive member function before a call to Bind. So, even though Windows implicitly binds the socket when I make a call to Send without first calling Bind, SFML does not allow me to Receive unless I first explicitly make a call to Bind with a port.

It doesn't make sense, how would you receive anything without listening to a specific port? It's like receiving e-mail without creating first an e-mail address.
However you can call Bind(0) to bind the socket to a free port (not sure if it works with SFML 1.6).

Quote
SFML also does not recognize that the port is set by Windows during a call to Send through it's GetPort member function.

This should be fixed in SFML 2.
Laurent Gomila - SFML developer

Wizzard

  • Full Member
  • ***
  • Posts: 213
    • View Profile
Distinguishing multiple clients with the same IP using UDP
« Reply #6 on: April 08, 2011, 09:54:40 am »
Quote from: "Laurent"
It doesn't make sense, how would you receive anything without listening to a specific port? It's like receiving e-mail without creating first an e-mail address.

I have not tested it to see if it works the way I think it does, but from what I understand of the Winsock documentation, it says that using Send with port 0 creates the "e-mail address" for me. I don't think I should have to recreate my "e-mail address" if the operating system does it for me.


Thanks for the responses though guys,
I guess I'll just begin converting all my code to SFML 2 in order to get the feature I need. :(

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Distinguishing multiple clients with the same IP using UDP
« Reply #7 on: April 08, 2011, 10:27:32 am »
Quote
from what I understand of the Winsock documentation, it says that using Send with port 0 creates the "e-mail address" for me

I may have answered too fast, yes. Calling Send on an unbound socket probably binds it to a random free port.

Quote
I guess I'll just begin converting all my code to SFML 2 in order to get the feature I need. :(

Don't be sad, it's worth the effort ;)
Laurent Gomila - SFML developer