I am in the process of creating a P2P application utilising UDP hole punching. Thanks to this amazing forum I was able to achieve that - I can establish a P2P connection between 2 devices! My app is based mostly on this post. My main goal is to create a reliable algorithm establishing a P2P connection between 2 devices.
The app is currently able to establish a connection - but it seems to me that it is very random, I need it to work reliable. There are 3 devices:
- My computer [A]
- Public server [B]
- Computer in a different,not local network [C]
My approach:
- Get to know the external ports and IP's of the devices
- Start sending UDP packets from [A] to [B] and vice versa, until connection established as the NAT's should match the internal and external ports
- Using Wireshark on both devices ([A] and [B]) to see the packet flow so I am not relying in case the application itself would have some issues
The issue: I have tried sending the packets for at least 10 minutes,with different frequencies from 10 packets every second, to one packet every 10 seconds, I would restart the devices and the routers, the packets would never go thorugh.
The solution: Usually after sending a couple packets from device [A], and stopping, then sending from device [B] then the connection would be established. Then both devices would be able to concurrently send and receive packets. This method is not reliable, I had to manually play around with sending the packets back and forth until the packets would start going through.
Both devices have the same application:
Initialising the UDP client:
private static UdpClient udpClient = new UdpClient();
public void SetUPUDP(IPEndPoint LocalEndPoint)
{
udpClient.ExclusiveAddressUse = false;
udpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
udpClient.Client.Bind(LocalEndPoint);
//https://stackoverflow.com/questions/7201862/an-existing-connection-was-forcibly-closed-by-the-remote-host
uint IOC_IN = 0x80000000;
uint IOC_VENDOR = 0x18000000;
uint SIO_UDP_CONNRESET = IOC_IN | IOC_VENDOR | 12;
udpClient.Client.IOControl((int)SIO_UDP_CONNRESET, new byte[] { Convert.ToByte(false) }, null);
}
The listening part:
public static async Task<string> StartListening(IPEndPoint LocalEndPoint)
{
Console.WriteLine("Listening on " + LocalEndPoint + ".");
byte[] buffer = udpClient.Receive(ref LocalEndPoint);
Console.WriteLine("Bytes received from " + LocalEndPoint + " " + Encoding.ASCII.GetString(buffer) + ".");
messageReceived = true;
return Encoding.ASCII.GetString(buffer);
}
The sending part
udpClient.Send(message, message.Length, RemoteEndPoint);
The question
I don't understand why the connection cannot be established whilst sending the packets concurrently. I need to create a reliable algorithm that I can repeat until the connection is established. I do not know whether the issue is in the code, as the app can send and receive packets concurrently, after the connection has been established. The packets were send with enough time in between that there should be no difference whether I stopped sending them or I am waiting to send the next one. But only after I stop sending the packets on [A] or [B], the packets will start going through.
Thank you in advance!