问题
I'm trying to add networking over the internet to my game, using Peer to Peer. I have already implemented a LAN only version, which uses .NET's peer to peer classes to connect within the local network.
I realized I need to use UDP hole punching in order to establish a connection to other clients that are behind a firewall.
This is how I have started to implement it: The server is a HTTP server using very simple PHP scripts to get the job done.
- register name on server, sending the private ip address and port as a GET variable
- when the server gets a registration request, it will save the public endpoint and the private endpoint
- request to connect to another client.
- the server will return the private and public endpoints of the client
- every two seconds, the second client will check in with the server, and if there is another client attempting to connect with it, it will get its endpoints too
- both clients start spamming each others public endpoints until they get a valid response
Now I have a bunch of questions
- Can the server be a HTTP server?
- When I make a request to an HTTP server, the client port changes each time a request is made. Is a private endpoint always matched to the same public endpoint?
- Does the request to the server have to have the same source endpoint as the UDP messages to the client?
- Is there a way to connect to an HTTP server in C# using a specified source endpoint?
- Are there any problems with my implementation?
Thanks!
回答1:
UDP hole punching is a complex topic, and many attempts have been made to find a solution that works. The problem is that there are so many different NAT routers out there, and there is no standard way of implementing NAT, so all routers behave a bit different.
Some attempts have been standardized, e.g. STUN, ICE. They still work only in most cases, not all, but they accumulate a lot of knowledge and address many concerns -- more than your attempt will ever be able to, simply because you can't test your solution with every NAT router under the sun. Skype, for example, spent years of perfecting its NAT traversal mechanism.
I recommend you have a look at STUN or preferably ICE. Try to implement one of them or look for existing implementations.
Another option might be to simply create a port forward at the router, e.g. using UPnP or NAT-PMP.
That said, I wouldn't be surprised if the .NET peer to peer classes came with a NAT traversal mechanism, but I'm not familiar with them.
回答2:
STUN is a best solution for the problem. it works for most of the scenarios.here is a simple example(C#) that gives you the NAT type,Local IP:Port and Public IP:Port.
try
{
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
socket.Bind(new IPEndPoint(IPAddress.Any, 0));
STUN_Result result = STUN_Client.Query("stunserver.org", 3478, socket);
Console.WriteLine("Net Type : " + result.NetType.ToString());
Console.WriteLine("Local IP : " + socket.LocalEndPoint.ToString());
if (result.NetType != STUN_NetType.UdpBlocked)
{
Console.WriteLine("Public IP : " + result.PublicEndPoint.ToString());
}
else
{
Console.WriteLine("");
}
}
catch (Exception x)
{
Console.WriteLine(x.StackTrace.ToString());
}
You can just add some breakpoints and check the behaviour of the code.
also you can traverse NAT using vs2010 onwords (.net4.0 < ) . there is a method AllowNATTraversal (bool value). set the value true for NAT Traverse. It uses Ipv6 address for connectivity. You can get Ipv6 global address from "Teredo" server by writing some commands in command prompt. Actually IPV6 is the technology that is used to avoid this problem.
来源:https://stackoverflow.com/questions/6794320/udp-hole-punching-help