Privire de ansamblu asupra NAT Punchthrough

Original: http://www.raknet.net/raknet/manual/natpunchthrough.html

Jenkins Software

Ce este NAT?

NAT este prescurtarea de la Network Address Translation. Acesta este utilizat de routere pentru a harta adrese din spatele router-ul la o adresă de destinație unică, folosind diferite porturi. De exemplu, dacă aveți două computere în spatele unui router, dar numai un singur ISP, atunci ambele computere va utiliza aceeași adresă IP, dar cu diferite porturi sursă decât ceea ce cererea de fapt atribuit. Router-ul păstrează un tabel de căutare a ceea ce mapări oferă, astfel încât atunci când un computer la distanță răspunde este direcționat către computerul local corect în spatele NAT.

Problema cu NAT este că computerele de la distanță nu poate iniția trimite la computere locale, deoarece nu există încă mapare. Prin urmare, în cazul în care două calculatoare, atât în ​​spatele NAT încerca să se conecteze, nu va fi capabil să facă acest lucru. Aceasta este o problemă de comunicare de voce, la egal la egal jocuri sau jocuri în cazul în care utilizatorii gazdă și gazdă este în spatele unui NAT. Pe vremuri utilizatorii ar trebui să meargă la ecranul lor configurare router si configurare o mapare. Cu toate acestea, în aplicațiile moderne utilizatorii nu sunt de obicei necesare pentru a face acest lucru, datorită NatPunchthrough.

NAT Punchthrough Prezentare generală

Plugin-ul NatPunchthroughClient.cpp necesită un server găzduit utilizator, nu în spatele NAT, care rulează NatPunchthroughServer.cpp că ambele clientii se pot conecta la. Serverul va găsi adresa IP externă a fiecărui client, și spune clientii sa se conecteze la acea adresă, în același timp. Dacă aceasta nu reușește, fiecare client va încerca să estimeze porturile utilizate de celălalt. Dacă aceasta nu reușește, procesul se repetă încă o dată, în cazul în care mai târziu a deschis portul estimare un port anterior. Dacă asta nu, de asemenea,, plugin-ul se întoarce ID_NAT_PUNCHTHROUGH_FAILED.

Nota 1: Dacă publicați prin Steam, oferim, de asemenea, SteamLobby, care utilizează servere gazduite de Valve, caz în care NATPunchthrough nu este necesară.
Nota 2: NAT Punchthrough nu este necesară în cazul în exclusivitate cu ajutorul IPv6.
Nota 3: În cazul în care jocul este doar client / server, s-ar putea aplica pur și simplu că serverele trebuie să sprijine UPnP. Vezi DependentExtensions \ miniupnpc-1.6.20120410. Cele mai multe routere sprijini acest aceste zile, și presupunând UPNP trece, oricine se poate conecta la tine.

NAT Punchthrough Algoritmul

  1.     Peer P1 vrea să se conecteze la egal la egal P2, ambii sunt conectate la un al treilea sistem de non-NAT, F
  2.     Peer P1 solicită OpenNAT (), cu RakNetGUID (identificator unic) de P2 la F.
  3.     F întoarce eșec dacă P2 nu este conectat, sau încercarea de deja punchthrough la P1.
  4.     F amintește de stat ocupat de P1 și P2. Dacă oricare dintre P1 sau P2 este ocupat, cererea este împins la o coadă. În caz contrar, cereri F cel mai recent port extern de la P1 și P2. P1 și P2 sunt marcate ca ocupat.
  5.     Dacă oricare dintre P1 sau P2 nu raspund punchthrough nu cu ID_NAT_TARGET_UNRESPONSIVE și steagul ocupat este unset. În caz contrar, F trimite mesaj legătură timestamped la P1 și P2 simultan.
  6.     P1 și P2 act identic în acest moment. În primul rând, ei trimit mai multe datagrame UDP la adrese interne LAN reciproc. Ei încearcă apoi extern IP / port celuilalt văzută de F. Porturile sunt încercat secvențial, până la MAX_PREDICTIVE_PORT_RANGE.
  7.     Dacă la un moment o datagrama ajunge la egal la egal la distanță, intrăm PUNCHING_FIXED_PORT stat. Datagrame sunt trimise doar la acea combinație IP / port restul algoritmului. Dacă răspunsul nostru ajunge pe sistemul de la distanta, NAT este considerat bidirecțională și ID_NAT_PUNCHTHROUGH_SUCCEEDED este returnat la utilizator.
  8.     Când NAT este deschis, sau dacă vom epuiza toate porturile, P1 și P2 trimite la F ca sunt gata pentru o nouă încercare punchthrough.


Algoritmul effectivness depinde de tipurile NAT implicate. Acesta va lucra cu oricare NAT este cel mai permisiv.

Con Full NAT: acceptă datagrame la un port care a fost utilizat anterior. Va accepta prima datagrama de la egal la egal la distanță.

Con NAT restrictionata Adresa: Acceptă datagrame la un port, atâta timp cât adresa IP a sursei datagrama este un sistem care le-am trimis deja la. Va accepta prima datagrama dacă ambele sisteme trimite simultan. În caz contrar, va accepta prima datagrama după ce am trimis o datagrama.

Port-restrictionata con NAT: La fel ca con-adresa restricționat NAT, dar a trebuit să trimită atât adresa corectă IP și portul la distanță de la distanță corect. Aceeași adresă sursă și portul la o altă destinație utilizează aceeași cartografiere.

Symmetric NAT: Un alt port este ales pentru fiecare destinație la distanță. Aceeași adresă sursă și portul la o altă destinație utilizează o mapare diferită. Având în vedere că portul va fi diferit, prima încercare punchthrough extern va eșua. Pentru ca acest lucru să-l lucreze nevoie de port-predicție (MAX_PREDICTIVE_PORT_RANGE> 1) și că router-ul alege porturi secvențial.

Succes Graph

Con Tip Router  Con Full NAT Con-Adresa restrictionata NAT Port-restrictionata NAT Simetric NAT
Con Full DA DA DA DA
Con-adresa restrictionata DA DA DA
Con restrictionata-Port DA DA DA NU
Simetric NAT DA DA NU NU



* Nu pot conecta în continuare, dacă estimarea de port funcționează, dar nu pot fi invocate.

Punerea în aplicare Client

  1.     Creați o instanță a plugin: NatPunchthroughClient natPunchthroughClient;
  2.     Atașați plugin la o instanță de RakPeerInterface: rakPeer-> AttachPlugin (și natPunchthroughClient);
  3.     Conecta la server, și așteptați pentru ID_CONNECTION_REQUEST_ACCEPTED. Utilizați următoarea linie de a utiliza serverul gratuit oferit de RakNet: rakPeer-> Connect (“natpunch.jenkinssoftware.com”, 61111, 0, 0);
  4.     Sunați OpenNAT cu RakNetGUID (identificator unic global) a sistemului de la distanță pe care doriți să vă conectați. În scopul de a obține RakNetGUID, va trebui să-l transmită cu propriul cod pe server, încărcați-l la PHPDirectoryServer, sau de a folosi un plugin care stochează, cum ar fi LightweightDatabase fie: natPunchthroughClient.OpenNAT (remoteGuid, serverSystemAddress) ;. Pentru a citi propriul RakNetGUID, folosiți RakPeerInterface :: GetGuidFromSystemAddress (UNASSIGNED_SYSTEM_ADDRESS);
  5.     Așteaptă un pic. Este posibil să dureze mai mult de 10 secunde pentru a încerca fiecare port posibil de două ori, deși de multe ori functioneaza în câteva secunde. Dacă doriți să obțineți mesaje text de pe ceea ce se întâmplă, puteți folosi NatPunchthroughClient :: SetDebugInterface ()
  6.     ID_NAT_PUNCHTHROUGH_SUCCEEDED înseamnă punchthrough reușit, și ar trebui să fie capabil să se conecteze sau trimite alte mesaje la sistemul de la distanță. Packet :: SystemAddress este adresa sistemului vă puteți conecta acum la. Orice altă ID_NAT_ * înseamnă punchthrough nu a reușit. Vezi MessageIdentifiers.h pentru lista de coduri și comentarii pe fiecare.

Punerea în aplicare server de

  1.     Gazdă un server undeva, nu folosind NAT / ex în spatele unui firewall. (RakNet oferă un unul gratuit la 8.17.250.34:60481, cu toate acestea s-ar putea dori să găzduiască propriul pentru uptime consistent).
  2.     Creați o instanță a plugin: NatPunchthroughServer natPunchthroughServer;
  3.     Atașați plugin: rakPeer-> AttachPlugin (și natPunchthroughServer);
  4.     Nu uita pentru a apela RakPeerInterface :: Startup () și RakPeerInterface :: SetMaximumIncomingConnections (MAX_CONNECTIONS);


Utilizarea clasa NatPunchthrough


A se vedea de propoziții\Samples\NATCompleteClient și \Samples\NATCompleteServer

UDP Proxy

Cu unele de slabă calitate sau routere casa, este posibil ca NAT punchthrough nu va funcționa. De exemplu, un router care alege un nou port aleator pentru fiecare conexiune de ieșire, și va permite doar conexiunile de intrare la acest port, nu va funcționa. Acest lucru se întâmplă aproximativ 5% din timp. Să se ocupe de acest caz, RakNet oferă sistemul UDPProxy. În esență, se folosește un server care tu a alerga pentru mesaje de traseu între sursă și destinație client transparent. Aceasta funcționează chiar și pentru datagrame rută din jocuri nu utilizează RakNet (deși aveți nevoie pentru a seta RakNet transmiterea). Combinația de NATPunchthrough și UDPProxy ar trebui să permită orice sistem să se conecteze la orice alt sistem cu o rata de succes de 100%, cu condiția sunteți dispus să găzduiască suficiente servere proxy pentru a transmite tot traficul.

Sistemul UDP Proxy foloseste 3 clase principale:

  •     UDPProxyClient: Face cereri de UDPProxyCoordinator la expediere de configurare. Aceasta este clasa clientului ruleaza.
  •     UDPProxyCoordinator: ruleaza pe serverul care va primi toate cererile de la UDPProxyClient. De asemenea, datele de conectare la toate devine UDPProxyServer
  •     UDPProxyServer: de fapt, nu la transmiterea datagrama UDP, prin intermediul unui exemplu compozit de UDPForwarder.cpp


Implementare Client:

  1.     Creați o instanță a plugin: UDPProxyClient udpProxyClient;
  2.     Deriva o clasa din RakNet :: UDPProxyClientResultHandler pentru a primi notificări de evenimente pentru sistemul.
  3.     Atașați plugin la o instanță de RakPeerInterface: rakPeer-> AttachPlugin (și udpProxyClient);
  4.     Suna UDPProxyClient :: SetResultHandler () de clasa creat la pasul 2.
  5.     Încercați NATPunchthrough primul. Dacă te ID_NAT_PUNCHTHROUGH_FAILED pentru sistemul care a inițiat NATPunchthrough, treceți la pasul 6. Ambele sisteme se va întoarce ID_NAT_PUNCHTHROUGH_FAILED, cu toate acestea, doar un sistem trebuie să înceapă sistemul proxy.
  6.     Suna UDPProxyClient :: RequestForwarding cu adresa coordonatorului, adresa pe care doriți să transmită la (UNASSIGNED_SYSTEM_ADDRESS pentru propria ta), adresa pe care doriți să transmită, și cât timp pentru a menține transmiterea activ pe nu există date. De exemplu:
    SystemAddress coordinatorAddress;
    coordinatorAddress.SetBinaryAddress (“8.17.250.34”);
    coordinatorAddress.port = 60481;
    udpProxyClient.RequestForwarding (coordinatorAddress, UNASSIGNED_SYSTEM_ADDRESS, p-> systemAddress, 7000);
  7.     Presupunând că sunt conectat la coordonatorului, și coordonatorul rulează plugin-ul, clasa tratare a evenimentului creat la pasul 2 ar trebui să obțineți un apel invers într-o secundă sau două. UDPProxyClientResultHandler :: OnForwardingSuccess vor fi returnate dacă un UDPProxyServer a fost atribuit de a transmite datagrame de la sistemul sursă specificat în pasul 6, la sistemul țintă specificat în pasul 6. De exemplu, să se conecteze la utilizarea sistemului de la distanță: rakPeer-> Connect ( proxyIPAddress, proxyPort, 0, 0);


Dacă mai mult de un server este disponibil, și ambele sisteme releu sursă și țintă se execută RakNet, apoi sursă și țintă va ping automat toate serverele disponibile. Serverele vor fi încercat în ordinea cea mai mică sumă ping la cel mai mare. Aceasta se bazează pe presupunerea că cea mai mică sumă de ping vă oferă server care are cea mai scurtă cale între cele două sisteme, și, prin urmare mai puțin lag.

Coordonator de implementare:

  1.     Creați o instanță a plugin: UDPProxyCoordinator udpProxyCoordinator;
  2.     Atașați plugin la o instanță de RakPeerInterface: rakPeer-> AttachPlugin (și udpProxyCoordinator);
  3.     Setați parola de pe coordonatorul pentru serverele de a utiliza udpProxyCoordinator.SetRemoteLoginPassword (COORDINATOR_PASSWORD);
  4.     Nu uita pentru a apela RakPeerInterface :: Startup () și RakPeerInterface :: SetMaximumIncomingConnections (MAX_CONNECTIONS);


Server de implementare:

  1.     Creați o instanță a plugin: UDPProxyServer udpProxyServer;
  2.     Atașați plugin la o instanță de RakPeerInterface: rakPeer-> AttachPlugin (și udpProxyServer);
  3.     Conectați-vă la coordonatorul
    Autentifica-te pentru a coordonatorului. Acest lucru se poate face în timpul rulării, astfel încât să puteți adăuga dinamic mai multe servere de expediere ca jocul este mai popular.
    udpProxyServer.LoginToCoordinator (COORDINATOR_PASSWORD, coordinatorSystemAddress);
  4.     Dacă plugin-ul coordonator este pe același sistem ca și plugin-ul de server, utilizați:
    udpProxyServer.LoginToCoordinator (COORDINATOR_PASSWORD, rakPeer-> GetInternalID (UNASSIGNED_SYSTEM_ADDRESS));
  5.     Dacă doriți să obțineți callback ca apar evenimente (în special de conectare eșec) provin din RakNet :: UDPProxyServerResultHandler și înregistrați clasă derivată cu UDPProxyServer :: SetResultHandler ()


Diagramă de stare cu UDP Proxy

Server hosting

Cerințe server

  1.     Nici o adresă de rețea traducere.
  2.     Nu firewall, firewall sau deschis pe porturile corespunzătoare.
  3.     Adresă IP statică. DNS dinamic este o modalitate de a obține în jurul valorii de această cerință.
  4.     Compila cu __GET_TIME_64BIT dacă doriți să rulați serverul mai mult de o lună fără a restarta
  5.     Lățime de bandă suficient să se ocupe de toate conexiunile


Soluții comerciale de hosting

Hypernia

  1.     Locații din întreaga lume. Servere sunt mașini individuale. Începând de la 150 $ pe luna


Dacă ați găsit mai solutii de gazduire, contactați-ne și va fi adăugate la această listă.

Comments are closed.