c# .net udp p2p hole-punching

c# - Ayuda de perforación UDP Hole



.net p2p (2)

Intento agregar redes a través de internet a mi juego, usando Peer to Peer. Ya he implementado una versión solo de LAN, que usa clases de igual a igual de .NET para conectarse dentro de la red local.

Me di cuenta de que necesito usar perforación UDP para establecer una conexión con otros clientes que están detrás de un firewall.

Así es como comencé a implementarlo: el servidor es un servidor HTTP que usa scripts PHP muy simples para hacer el trabajo.

    • registrar el nombre en el servidor, enviando la dirección IP privada y el puerto como una variable GET
    • cuando el servidor recibe una solicitud de registro, guardará el punto final público y el punto final privado
    • solicitud para conectarse a otro cliente.
    • el servidor devolverá los extremos privados y públicos del cliente
    • cada dos segundos, el segundo cliente se registrará con el servidor, y si hay otro cliente que intenta conectarse con él, también obtendrá sus puntos finales
    • ambos clientes comienzan a enviar spam a los puntos finales públicos hasta que obtienen una respuesta válida

Ahora tengo un montón de preguntas

  1. ¿Puede el servidor ser un servidor HTTP?
  2. Cuando realizo una solicitud a un servidor HTTP, el puerto del cliente cambia cada vez que se realiza una solicitud. ¿Un extremo privado siempre coincide con el mismo extremo público?
  3. ¿La solicitud al servidor debe tener el mismo extremo fuente que los mensajes UDP para el cliente?
  4. ¿Hay alguna forma de conectarse a un servidor HTTP en C # utilizando un punto final fuente específico?
  5. ¿Hay algún problema con mi implementación?

¡Gracias!


La perforación de agujeros UDP es un tema complejo, y se han realizado muchos intentos para encontrar una solución que funcione. El problema es que existen tantos enrutadores NAT diferentes, y no existe una forma estándar de implementar NAT, por lo que todos los enrutadores se comportan de forma un poco diferente.

Algunos intentos han sido estandarizados, por ejemplo, STUN , ICE . Todavía funcionan solo en la mayoría de los casos, no en todos, pero acumulan muchos conocimientos y abordan muchas inquietudes, más de las que su intento podrá lograr, simplemente porque no puede probar su solución con cada enrutador NAT bajo el sol. . Skype, por ejemplo, pasó años perfeccionando su mecanismo NAT transversal.

Te recomiendo que eches un vistazo a STUN o preferiblemente ICE . Intenta implementar uno de ellos o busca implementaciones existentes.

Otra opción podría ser simplemente crear un puerto de reenvío en el enrutador, por ejemplo, usando UPnP o NAT-PMP .

Dicho esto, no me sorprendería si las clases .NET peer to peer llegaran con un mecanismo transversal NAT, pero no estoy familiarizado con ellas.


STUN es la mejor solución para el problema. funciona para la mayoría de los escenarios. Aquí hay un ejemplo simple (C #) que le proporciona el tipo de NAT, IP local: Puerto e IP pública: Puerto.

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

Puede agregar algunos puntos de interrupción y verificar el comportamiento del código.

también puede atravesar NAT utilizando vs2010 onwords (.net4.0 <). hay un método AllowNATTraversal (valor bool). establecer el valor verdadero para NAT Traverse. Utiliza la dirección Ipv6 para la conectividad. Puede obtener la dirección global Ipv6 del servidor "Teredo" escribiendo algunos comandos en el símbolo del sistema. En realidad, IPV6 es la tecnología que se utiliza para evitar este problema.