Я пытаюсь выполнить пробивание отверстий UDP. Я основываю свою теорию на этой статье и этой странице WIKI , но у меня возникли некоторые проблемы с ее кодированием на C #. Вот моя проблема:
Используя код, который был размещен здесь , теперь я могу подключиться к удаленному компьютеру и прослушивать один и тот же порт для входящих подключений (привязать 2 UDP-клиента к одному и тому же порту) .
По какой-то причине две привязки к одному и тому же порту блокируют друг друга от получения каких-либо данных. У меня есть UDP-сервер, который отвечает на мое соединение, поэтому, если я сначала подключаюсь к нему, прежде чем привязывать любого другого клиента к порту, я получаю его ответы обратно.
Если я привяжу к порту другого клиента, ни один из клиентов не получит данные.
Ниже приведены 2 фрагмента кода, которые показывают мою проблему.Первый подключается к удаленному серверу для создания правила на устройстве NAT, а затем в другом потоке запускается прослушиватель для захвата входящих пакетов. Затем код отправляет пакеты на локальный IP-адрес, чтобы прослушиватель их получил. Второй только отправляет пакеты на локальный IP-адрес, чтобы убедиться, что это работает. Я знаю, что это не настоящая пробивка дыр, так как я отправляю пакеты себе, вообще не живя на устройстве NAT. На данный момент я столкнулся с проблемой, и я не думаю, что все будет по-другому, если я буду использовать для подключения компьютер, не подключенный к устройству NAT.
[РЕДАКТИРОВАТЬ] 4 февраля 2012 г. Я попытался использовать другой компьютер в своей сети и WireShark (сниффер пакетов), чтобы проверить слушателя. Я вижу пакеты, поступающие с другого компьютера, но не получаемые UDP-клиентом слушателя (udpServer) или UDP-клиентом отправителя (клиент).
[РЕДАКТИРОВАТЬ] 05.02.2010 Теперь я добавил вызов функции для закрытия первого клиента UDP после начальной отправки и получения пакетов, живущих только со вторым клиентом UDP для прослушивания порта. Это работает, и я могу получать пакеты изнутри сети на этот порт. Теперь я попытаюсь отправлять и получать пакеты из-за пределов сети. Я опубликую свои выводы, как только что-нибудь найду.
Используя этот код, я получаю данные о слушающем клиенте:
static void Main(string[] args)
{
IPEndPoint localpt = new IPEndPoint(Dns.Resolve(Dns.GetHostName()).AddressList[0], 4545);
ThreadPool.QueueUserWorkItem(delegate
{
UdpClient udpServer = new UdpClient();
udpServer.ExclusiveAddressUse = false;
udpServer.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
udpServer.Client.Bind(localpt);
IPEndPoint inEndPoint = new IPEndPoint(IPAddress.Any, 0);
Console.WriteLine("Listening on " + localpt + ".");
byte[] buffer = udpServer.Receive(ref inEndPoint); //this line will block forever
Console.WriteLine("Receive from " + inEndPoint + " " + Encoding.ASCII.GetString(buffer) + ".");
});
Thread.Sleep(1000);
UdpClient udpServer2 = new UdpClient(6000);
// the following lines work and the data is received
udpServer2.Connect(Dns.Resolve(Dns.GetHostName()).AddressList[0], 4545);
udpServer2.Send(new byte[] { 0x41 }, 1);
Console.Read();
}
Если я использую следующий код, после соединения и передачи данных между моим клиентом и сервером слушающий UDP-клиент ничего не получит:
static void Main(string[] args)
{
IPEndPoint localpt = new IPEndPoint(Dns.Resolve(Dns.GetHostName()).AddressList[0], 4545);
//if the following lines up until serverConnect(); are removed all packets are received correctly
client = new UdpClient();
client.ExclusiveAddressUse = false;
client.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
client.Client.Bind(localpt);
remoteServerConnect(); //connection to remote server is done here
//response is received correctly and printed to the console
ThreadPool.QueueUserWorkItem(delegate
{
UdpClient udpServer = new UdpClient();
udpServer.ExclusiveAddressUse = false;
udpServer.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
udpServer.Client.Bind(localpt);
IPEndPoint inEndPoint = new IPEndPoint(IPAddress.Any, 0);
Console.WriteLine("Listening on " + localpt + ".");
byte[] buffer = udpServer.Receive(ref inEndPoint); //this line will block forever
Console.WriteLine("Receive from " + inEndPoint + " " + Encoding.ASCII.GetString(buffer) + ".");
});
Thread.Sleep(1000);
UdpClient udpServer2 = new UdpClient(6000);
// I expected the following line to work and to receive this as well
udpServer2.Connect(Dns.Resolve(Dns.GetHostName()).AddressList[0], 4545);
udpServer2.Send(new byte[] { 0x41 }, 1);
Console.Read();
}