Much clearer now, thanks. Leaves me with 1 more question: What happens when there's let's say 10 clients behind a NAT and 2 of them random the same port? Will the router manage? Or do I have to handle such an event in the client app (if so, how to detect it?).
If two clients are behind the same NAT, the router will not allocate the same external port for both clients.
As a server, you should bind to a known port, on a known address, and receive packets using recvfrom().
recvfrom() will tell you the address you should reply to. This will generally be the external IP/port combination of each client.
As a client, you should just create a socket, and call sendto() to the server ip:port.
The first time you do this, the UDP implementation will bind to some random port on the local machine.
That same port will be re-used for eacn successive sendto().
The NAT gateway between the client and the server will map that inner ip:port to some UNIQUE outer ip:port, which is visible to the server.
For all intents and purposes, that outer ip:port is "the address of the client" for the server.
There is one special case: If the server and the client are behind the same NAT gateway, some NAT gateways do not do "hairpin" NAT where they will allow an inside-initiated connection to an inside-exposed server. This is mainly the case when you use NAT punch-through for user-hosted servers.
The solution to that problem is to discover that the client and the server are on the same network -- for example, by the server's public and private IP both being available in discovery, and each client trying the internal IP first. Might want to use some random session ID as part of that protocol, too, to make sure it doesn't get confused with other things running :-)