打洞实施 [英] UDP hole punching implementation

查看:183
本文介绍了打洞实施的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图完成打洞。我立足我的理论在这篇文章这的 WIKI页面,但我面临着它的C#代码的一些问题。这里是我的问题:



使用已发布的代码的这里我现在能够连接到远程计算机,听相同的端口进入的连接(绑定2个UDP客户端相同的端口)。在



由于某些原因,两个绑定到同一端口阻止对方接收的任何数据。
我有,所以如果我连接到它的回应我的连接第一任何其他客户端绑定到该端口,我得到它的响应返回前一个UDP服务器。



如果我另外一个客户绑定到任何数据将是客户机接收端口。



以下是2的代码段,显示我的问题。首先连接到远程服务器创建NAT设备上的规则,然后侦听器开始在不同的线程来捕获传入数据包。然后,代码发送数据包到本地IP让听者会得到它。第二只发送数据包到本地IP,以确保这个工程。我知道这是不是实际打孔,因为我将报文的独处而生活在NAT设备都没有。我面临的一个问题在这一点上,我不想象这会有什么不同,如果我用电脑出方NAT设备进行连接。



2012年2月4日
我试着用另一台电脑我的网络和Wireshark(数据包嗅探器)来测试监听器。我看到从其他计算机传入的数据包,但不被听众UDP客户端(udpServer)或者发件人UDP客户端(客户端)接收



2 / 5/2010
我现在已经增加了一个函数调用的初始发送和接收的数据包仅居住在第二UDP客户端监听端口上的后关闭第一UDP客户端。这工作,我可以从该端口上的网络内接收数据包。现在我会尝试发送和来自网络外部接收数据包。我会,只要我找到的东西后我发现



使用这个代码,我得到的监听客户端上的数据:

 静态无效的主要(字串[] args)
{
IPEndPoint localpt =新IPEndPoint(Dns.Resolve(Dns.GetHostName())。AddressList中[0 ],4545);

ThreadPool.QueueUserWorkItem(代表
{
UdpClient udpServer =新UdpClient();
udpServer.ExclusiveAddressUse = FALSE;
udpServer.Client.SetSocketOption( SocketOptionLevel.Socket,SocketOptionName.ReuseAddress,真);
udpServer.Client.Bind(localpt);

IPEndPoint inEndPoint =新IPEndPoint(IPAddress.Any,0);
控制台.WriteLine(听的+ localpt +。);
字节[]缓冲= udpServer.Receive(REF inEndPoint); //这条线将永远阻止
Console.WriteLine(从接收+ inEndPoint ++ Encoding.ASCII.GetString(缓冲器)+。);
});

Thread.sleep代码(1000);

UdpClient udpServer2 =新的UdpClient(6000);

//以下行的工作和数据接收
udpServer2.Connect(Dns.Resolve(Dns.GetHostName())AddressList中[0],4545。);
udpServer2.Send(新的byte [] {}×41,1);

Console.Read();
}

如果我使用下面的代码,我的客户端之间的连接和数据传输后和服务器,监听UDP客户端将不会收到任何东西:

 静态无效的主要(字串[] args)
{
IPEndPoint localpt =新IPEndPoint(Dns.Resolve(Dns.GetHostName())AddressList中[0],4545);

//如果下面的行直到serverConnect();被删除的所有数据包都正确收到
客户端=新UdpClient();
client.ExclusiveAddressUse = FALSE;
client.Client.SetSocketOption(SocketOptionLevel.Socket,SocketOptionName.ReuseAddress,真正的);
client.Client.Bind(localpt);
remoteServerConnect(); //连接到远程服务器都是在这里完成
//响应被正确接收并打印到控制台

ThreadPool.QueueUserWorkItem(代表
{
UdpClient udpServer =新UdpClient();
udpServer.ExclusiveAddressUse = FALSE;
udpServer.Client.SetSocketOption(SocketOptionLevel.Socket,SocketOptionName.ReuseAddress,真正的);
udpServer.Client.Bind(localpt);

IPEndPoint inEndPoint =新IPEndPoint(IPAddress.Any,0);
Console.WriteLine(听的+ localpt +。);
字节[]缓冲= udpServer。接收(REF inEndPoint); //这条线将永远阻止
Console.WriteLine(+ inEndPoint ++ Encoding.ASCII.GetString(缓冲)+,从接收);
} );

Thread.sleep代码(1000);

UdpClient udpServer2 =新的UdpClient(6000);

//我期待下面的行工作,并接受这个问题,以及
udpServer2.Connect(Dns.Resolve(Dns.GetHostName())AddressList中[0],4545。);
udpServer2.Send(新的byte [] {}×41,1);

Console.Read();
}


解决方案

如果我没有理解错,你尝试每2客户端背后不同的NAT之间进行通信对等网络,使用打孔的中介服务器?



几年前,我做了同样的事情在C#中,我还没有找到没有代码,但我给你一些指针,如果你喜欢:



首先,我不会使用Connect()函数在udpclient,因为UDP是无连接协议,这一切的功能确实是隐藏UDP套接字的功能。



您应该亲热以下步骤:




  1. 打开一个UDP套接字与它的服务器不被防火墙阻止端口,在一个特定的端口(如绑定此套接字连接到选择的端口,例如23000)

  2. 创建一个UDP套接字第一个客户端,并在23000送东西给服务器的不要将此套接字绑定即可。当使用UDP发送一个数据包时,Windows会自动自由港分配到插座

  3. 从其他客户做同样

  4. 的现在服务器已经在2个不同端口2个不同不会忽略收到2包2的客户端。如果测试服务器可以在同一个地址和端口发送数据包回。 (如果这不工作,你做错了什么,或你的NAT是不工作你知道它的工作,如果你可以在不打开端口玩游戏:D)

  5. 服务器现在应该送地址和其他客户端的端口,每个连接的客户端。

  6. 现在,客户端应该能够发送使用UDP从服务器接收到的不会忽略的数据包。



您应该注意到,在NAT使用的端口可能不是同一个端口作为客户端PC!服务器应该这个外部端口分发到客户端。 您必须使用外部地址还有外​​部端口发送给!



另外请注意,你的NAT可能不支持这种端口转发。一些NAT的正向所有传入流量分配的端口给您的客户端,这是你想要的东西上。但一些NATS不过滤的传入数据包不会忽略,因此可能会阻止其他客户端的数据包。使用标准的个人用户的路由器虽然当这是不可能的。


I am trying to accomplish UDP hole punching. I am basing my theory on this article and this WIKI page, but I am facing some issues with the C# coding of it. Here is my problem:

Using the code that was posted here I am now able to connect to a remote machine and listen on the same port for incoming connections (Bind 2 UDP clients to the same port).

For some reason the two bindings to the same port block each other from receiving any data. I have a UDP server that responds to my connection so if I connect to it first before binding any other client to the port I get its responses back.

If I bind another client to the port no data will be received on either clients.

Following are 2 code pieces that show my problem. The first connects to a remote server to create the rule on the NAT device and then a listener is started on a different thread to capture the incoming packets. The code then sends packets to the local IP so that the listener will get it. The second only sends packets to the local IP to make sure this works. I know this is not the actual hole punching as I am sending the packets to myself without living the NAT device at all. I am facing a problem at this point, and I don't imagine this will be any different if I use a computer out side the NAT device to connect.

[EDIT] 2/4/2012 I tried using another computer on my network and WireShark (packet sniffer) to test the listener. I see the packets incoming from the other computer but are not received by the listener UDP client (udpServer) or the sender UDP client (client).

[EDIT] 2/5/2010 I have now added a function call to close the first UDP client after the initial sending and receiving of packets only living the second UDP client to listen on the port. This works and I can receive packets from inside the network on that port. I will now try to send and receive packets from outside the network. I will post my findings as soon as I find something.

Using this code I get data on the listening client:

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();
}

If I use the following code, after the connection and data transfer between my client and server, the listening UDP client will not receive anything:

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();
}

解决方案

If i understand correctly, you are trying to communicate peer-to-peer between 2 clients each behind a different NAT, using a mediation server for hole punching?

Few years ago i did the exact same thing in c#, i haven't found the code yet, but ill give you some pointers if you like:

First, I wouldn't use the Connect() function on the udpclient, since UDP is a connectionless protocol, all this function really does is hide the functionality of a UDP socket.

You should perfrom the following steps:

  1. Open a UDP socket on a server with it's ports not blocked by a firewall, at a specific port (eg Bind this socket to a chosen port for example 23000)
  2. Create a UDP socket on the first client, and send something to the server at 23000. Do not bind this socket. When a udp is used to send a packet, windows will automatically assign a free port to the socket
  3. Do the same from the other client
  4. The server has now received 2 packets from 2 clients at 2 different adresses with 2 different ports. Test if the server can send packets back on the same address and port. (If this doesn't work you did something wrong or your NAT isn't working. You know its working if you can play games without opening ports :D)
  5. The server should now send the address and port of the other clients to each connected client.
  6. A client should now be able to send packets using UDP to the adresses received from the server.

You should note that the port used on the nat is probably not the same port as on your client pc!! The server should distribute this external port to clients. You must use the external adresses and the external ports to send to!

Also note that your NAT might not support this kind of port forwarding. Some NAT's forward all incoming traffic on a assigned port to you client, which is what you want. But some nats do filtering on the incoming packets adresses so it might block the other clients packets. This is unlikely though when using a standard personal user router.

这篇关于打洞实施的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆