Udp Hole Punching Implementation

UDP hole punching. Have server talk to client

Finally found the answer! Here is the implemenation with just a client and a server. My next attempt will be to use 3 computers. anyways hope this helps:

Server code:

class Program
{
static byte[] dataToSend = new byte[] { 1, 2, 3, 4, 5 };

// get the ip and port number where the client will be listening on
static IPEndPoint GetClientInfo()
{
// wait for client to send data
using (UdpClient listener = new UdpClient(11000))
{
IPEndPoint groupEP = new IPEndPoint(IPAddress.Any, 11000);
byte[] receive_byte_array = listener.Receive(ref groupEP);

return groupEP;
}
}

static void Main(string[] args)
{
var info = GetClientInfo(); // get client info

/* NOW THAT WE HAVE THE INFO FROM THE CLIENT WE ARE GONG TO SEND
DATA TO IT FROM SCRATCH!. NOTE THE CLIENT IS BEHIND A NAT AND
WE WILL STILL BE ABLE TO SEND PACKAGES TO IT
*/

// create a new client. this client will be created on a
// different computer when I do readl udp punch holing
UdpClient newClient = ConstructUdpClient(info);

// send data
newClient.Send(dataToSend, dataToSend.Length);
}

// Construct a socket with the info received from the client
static UdpClient ConstructUdpClient(IPEndPoint clientInfo)
{
var ip = clientInfo.Address.ToString();
var port = clientInfo.Port;

// this is the part I was missing!!!!
// the local end point must match. this should be the ip this computer is listening on
// and also the port
UdpClient client = new UdpClient(new IPEndPoint( IPAddress.Any, 11000));

// lastly we are missing to set the end points. (ip and port client is listening on)

// the connect method sets the remote endpoints
client.Connect(ip, port);

return client;
}
}

client code:

string ipOfServer = "192.168.0.139";
int portServerIsListeningOn = 11000;

// send data to server
Socket sending_socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
IPAddress send_to_address = IPAddress.Parse(ipOfServer);
IPEndPoint sending_end_point = new IPEndPoint(send_to_address, portServerIsListeningOn);
sending_socket.SendTo(Encoding.ASCII.GetBytes("Test"), sending_end_point);

// get info
var port = sending_socket.LocalEndPoint.ToString().Split(':')[1];

// now wait for server to send data back
IPEndPoint groupEP = new IPEndPoint(IPAddress.Any, int.Parse(port));
byte[] buffer = new byte[1024];
sending_socket.Receive(buffer); // <----- we can receive data now!!!!!

UDP hole Punching

1) Yes, with most reasonable firewalls, unless you configure it in extremely paranoid mode.

2) Not exactly. This article explains it in more detail, but the idea is that one of the clients first sends a datagram to the other's public IP. Then this datagram is discarded, but the other client knows that it was sent because the first one told it through the server. Then the other client sends a datagram back to the first one to the same port from which the first datagram originated. Since NAT at the first client remembers that there was a packet from that port, it considers the incoming datagram to be a reply to the first one. The problem here is to figure out which public port NAT will choose to send the first datagram, but most NATs do it in a predictable way so it almost always works fine, sometimes just not from the first try.



Related Topics



Leave a reply



Submit