UDP Hole Punching (c++/winsock)

2019-08-03 09:44发布

问题:

stackoverflow users!

I have an app that has to deal with p2p, and that's how I get to UDP Hole punching. But I ran into troubles with implementation. Hope, you can give me some tips.

I've got server, which works perfect and introduces clients to eachother, but clients can't connect probably because of my small exp working with sockets. So, client algo is:

  1. Create udp socket (socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);)
  2. Send message to server via sendto function
  3. Use recvfrom locker function to get an answer from server

After those 3 steps I get peer endpoint. Next, I was trying to connect clients in two ways:

Way1:

  1. Use the same socket to send data to peer via sendto function, but passing another sockaddr
  2. Listen with recvfrom locker function (And at that point I'm getting WSAECONNRESET error)

Way2:

  1. Create new socket
  2. Bind it
  3. Use it to send data to peer
  4. Listen

In that way one client fails on binding and another fails on listening with errors WSAEADDRINUSE and WSAECONNRESET. I'm obviously doing something wrong and your help would be highly appreciated. Thanks in advance.

P.S. Wanna share a good article about UDP Hole Punching in order to help those, who is new to this technique: http://www.brynosaurus.com/pub/net/p2pnat/

回答1:

If you read the documentation for recvfrom(), it says:

WSAECONNRESET

The virtual circuit was reset by the remote side executing a hard or abortive close. The application should close the socket; it is no longer usable. On a UDP-datagram socket this error indicates a previous send operation resulted in an ICMP Port Unreachable message.

Which means your call to sendto() is failing. That makes sense if one or both clients are behind a router. Based on your description (and lack of code), you are not actually performing any hole punching to open up the router(s) to allow client-to-client packets to pass through. You have only sent a message to your server, which allows for client-to-server and server-to-client packets to pass through. A few more packet exchanges between each client and the server are required to perform the hole punching on each end, as described in detail in the article you linked to. Are you actually doing what the article says to do?