1234

Ersteller
Husi012
In den letzten 60 min online
Husi012
Rang 3

Projekte: 1
Designs: 0
Blogs: 2
Aktivität:
Aktiv
Tunneling bzw. Firewall hole punching? 13.09.2015 - 16:39

Hi

Ich hab mich gefragt, ob es auch eine andere Lösung gibt, ein Multiplayer Game zu machen, ohne einen gemieteten Server zu benutzen. 

Ich hab im Netz gegoogled und hab etwas zu Tunneling bzw. Firewall hole punching gefunden. Hier soll man die Daten so konvertieren, dass die Firewall denkt, dass es normale http Sachen sind und die Daten durchlässt.

Meine Frage. Wie konvertiert man das? Dazu hab ich noch nichts gefunden... Ist es sehr kompliziert, oder muss man nur die Headerdaten verändern? Wäre echt cool wenn Jemand das weis 


Ein Bug ist mehr als ein Bug.... es ist ein .... Feature.... ähh natürlich ein Käfer!!

Meine Eigene Seite: Hier klicken

GWRon
In den letzten 60 min online
GWRon
Rang 6

Projekte: 2
Designs: 3
Blogs: 7
Aktivität:
Sehr aktiv
14.09.2015 - 19:54

Also ich wuerde folgendes tun:

Wir haben 2 Clients "A" und "B" - und einen Server "S". Das Problem ist: A kennt B nicht, und weiss nicht wie es B kontaktieren koennte (welche Ports sind offen? Wie ist seine IP?). Gleiches gilt fuer B.

Was aber beide Clients wissen ist, wie sie den Server S erreichen koennen. Also melden sie sich bei S (Loginserver, Match-Making-Server, Lobby ...).

Von nun an weiss S: A sendet seine UDP (davon geh ich jetzt mal aus)-Pakete ueber den Port 1234 - die Ports koennen bei jedem "Netzwerk-Stream"-Erstellen anders sein, je nachdem, was gerade frei ist. Auch weiss S nun ueber B bescheid, der sendet gerade ueber 9876.

Dadurch dass sowohl A als auch B die Verbindung zu S initiert haben (ausgehender Traffic) wird auf beiden Seiten eine potentiell existierende Firewall automatisch den Datenverkehr zu S erlauben.
Zustand nun: A kann an S senden. B kann an S senden. S kann an A und B senden (moegliche Firewalls von A und B haben nun S auf der "whitelist").

 

Okay, aber wie kommen nun A und B zueinander? Brauchen sie nun immer S als "Relay" (Weitervermittler) ? Nein, dass waere nur der Fall, wenn man "A" nie direkt mit "B" kommunizieren lassen woellte (die IP der anderen Mitspieler nicht veroeffentlichen will).

Nun sendet S einfach an B, dass man A ueber den Port 1234 erreichen kann. Und an A sendet S, dass B ueber den Port 9876 erreichbar ist.

 

Mit den neuen Informationen versucht nun A den B zu erreichen - das kann per sofort klappen, oder aber es benoetigt einen Zwischenschritt. B hat vielleicht eine Firewall die erstmal den unbekannten eingehenden Traffic abblockt (sie akzeptiert auf dem Port nur Daten von S). Schade, Paket 1 von A zu B ist geblockt. Aber B will ja auch mit A verbinden, also sendet B an A mit Port 1234. Hey, A hat auch so eine doofe Firewall die eigentlich nur von S Pakete auf Port 1234 entgegen wuerde... aber halt! Da A vorher schon an B versucht hat ein Datenpaket zu schicken (ueber Port 1234 hin zu B mit Port 9876), akzeptiert A von nun an auch Pakete von B die bei A auf Port 1234 eintrudeln.

Von nun an kann auch A an B Daten schicken, denn B hat nun ebenfalls an A ein Paket gesendet und somit die "Antworten" von A auf Port 9876 freigegeben.

 

 

Kurzfassung:
- Client A und B koennen nur Server S kontaktieren (dessen Daten sind bekannt)
- Server S teilt Client A die Kontaktdaten von B mit (Absende-IP:Absende-Port)
- A und B haben durch die Kontaktaufnahme mit S ihre (moeglicherweise existierenden) Firewalls in Richtung S geoffnet
- A kann B nicht erreichen (Bs Firewall blockt) und B den A nicht (As Firewall  blockt)
- durch den Kontaktversuch von A nach B werden Antworten von B ab sofort durchgestellt
- B kann nun per sofort den A kontaktieren, was wiederum Antworten von A ermoeglicht 

 

 

So, ich hoffe das hat ein wenig Klarheit geschaffen. 

 

bye
Ron


Ersteller
Husi012
In den letzten 60 min online
Husi012
Rang 3

Projekte: 1
Designs: 0
Blogs: 2
Aktivität:
Aktiv
15.09.2015 - 16:39

Das heißt, dass die Firewalls ein Datenverkehr durchlassen, nur wenn beide sich gegeneinander kontaktieren?

Ich bin jetzt nicht auf dem Spezialgebiet. Dan müssten doch beide eigentlich Server und Client gleichzeitig sein oder?

 

Danke das du eine so ausführliche Nachricht gepostet hast 


Ein Bug ist mehr als ein Bug.... es ist ein .... Feature.... ähh natürlich ein Käfer!!

Meine Eigene Seite: Hier klicken

GWRon
In den letzten 60 min online
GWRon
Rang 6

Projekte: 2
Designs: 3
Blogs: 7
Aktivität:
Sehr aktiv
15.09.2015 - 23:36

Naja, nennen wir es mal nicht "Server und Client".

Bei einem Server-Client-Spiel, braeuchtest Du kein "hole punching", da alle Clients nur mit dem Server kommunizieren wuerden - und die Clients muessten fuer die Erstkontaktaufnahme ja sowieso den Server kennen (IP:port). Da sie die Verbindung aufbauen, kann der Server auch auf dem genutzten Absender-Port antworten.

Server-Client sind Spiele, bei dem die komplette Welt auf dem Server simuliert wird - die Clients machen lokal dann zwar auch Dinge, verwerfen diese Zustaende aber wieder, wenn vom Server Korrekturen eintrudelt:

Client -> Server: "Ich habe Unit 123 gekillt"
Client: Spiele Todesanimation fuer Unit 123 ab
Server -> Client: "Nein, Du warst zu spaet, Client2 hat schon gekillt"
Client: Stelle Unit123 wieder hin (bzw zeige, dass der Spieler von Client2 die Einheit gekillt hat)

 

Ok, bei einer "Client-Client"-Kommunikation unterhalten sich alle Spieler mit allen anderen Spielern. Meiner Meinung war dies teilweise bei Warcraft 3 (also sicher auch StarCraft 1 + 2) der Fall. Deswegen hatten dort auch alle Spieler Lags wenn einer "lahmte" (LockStep-Logiksystem).

Was sich anbietet: Lobbysystem ist Server-Client basiert, das eigentliche Spiel ist dann aber Peer2Peer (Client-Client). Der Server macht sozusagen die Spielerclients nur noch miteinander bekannt.

 

Kurzum:
Wenn Client 1 an den Server  ein Paket gesendet hat, erlaubt er dem Server zu antworten (an den beim Absenden genutzten Port).
Der Server sendet als Antwort an Client 1 alle anderen eingeloggten Client-IP/ports.
Er tut dies erneut, wenn sich ein anderer Spieler einklinkt
Client 1 kennt nun alle IP:Ports der Mitspieler und sendet ein Paket an eben diese Spieler -und erlaubt somit (seiner Firewall), dass diese Antworten an ihn schicken.
Je nach Firewall blocken die anderen Clients aber erstmal das Paket von Client 1. Da sie aber nun ebenfalls mit Client 1 Kontakt aufnehmen, schalten sie in ihren Firewalls die Antworten von Client 1 frei.
Das naechste Eintrudeln eines Client1-Paketes bei den anderen Clients kommt dann an der Firewall vorbei.

 

bye
Ron


Ersteller
Husi012
In den letzten 60 min online
Husi012
Rang 3

Projekte: 1
Designs: 0
Blogs: 2
Aktivität:
Aktiv
16.09.2015 - 16:37

Ok,

Feine Sache. Wozu muss man denn den Port hochladen? In dem Sinne kann man doch irgendein Port einfach festlegen. Oder versteh ich da was falsch?


Ein Bug ist mehr als ein Bug.... es ist ein .... Feature.... ähh natürlich ein Käfer!!

Meine Eigene Seite: Hier klicken

GWRon
In den letzten 60 min online
GWRon
Rang 6

Projekte: 2
Designs: 3
Blogs: 7
Aktivität:
Sehr aktiv
17.09.2015 - 09:24

Klar kannst Du den Port festlegen ... wenn du TCP benutzt. Fuer Spiele wird aber haeufiger UDP + eine Kontrollschicht benutzt.

Vereinfacht:
- TCP kuemmert sich darum, dass Pakete in der Reihenfolge ankommen, wie sie versendet worden sind - und dass sie ueberhaupt ankommen
- UDP: sendet und sendet auf Teufel komm raus. Reihenfolge egal, Ankunft? Mir doch wurst

Wenn man also UDP nutzt, koennten Pakete nie ankommen oder durcheinandergewuerfelt. Das muss dann Dein Programm abfangen (gib jedem UDP-Paket eine Checksumme mit, gib jedem eine aufsteigende Nummer mit). Der Client speichert dann solange Pakete zwischen, bis das Paket da ist, was auf das letzte "verarbeitete" folgt ... dann alle in der Warteschlange abarbeiten, die auf den Neuankoemmling "draufpassen" - dann wieder warten bis die naechste Luecke gefuellt ist usw. usf.

 

Zurueck zu den Ports: bei TCP kann man den Port raussuchen, UDP hingegen nimmt einfach "den naechst besten". Deswegen weisst Du nicht, welchen Port du nehmen wirst - Dein Gegenueber hingegen bekommt ja mit dem ihm zugestellten Paket auch die Absenderinfos (IP:PORT) und kann dann explizit an diese antworten.

Deswegen ist es von Vorteil, die Lobby per "TCP" zu realisieren (bzw ich mache das bei TVTower nur fuer den "Spiel-Ankuendigen-Kanal"), denn da gibt man den Port vor (das ist dann der, der im LAN freigegeben werden sollte - also in der Software-Firewall). in dem "Spiel-XYZ-mit-5von10Spielern-Paket" ist dann auch die Kontaktadresse des "Host-Clients" enthalten - also IP:PORT - und an die kann sich dann der Client ja wenden -sprich Erstkontakt, von da an kann der Host-Client dem Client antworten (siehe letzter Post) usw usf.

Statt dem Ankuendigungs-Kanal kannst Du aber auch einen Onlineserver zwischenschalten - also einen "http://www.domain.de/api/get/games" oder aehnliches, der dann eben diese Funktion uebernimmt... dann laeuft alles "erstmalige" ueber Port 80 (bei nicht-ssl). Geht auch.

 

Kurzum:
Du kannst Dir bei UDP den Port nicht so raussuchen, musst also anderweitig an den "offenen Port" der anderen Clients kommen - die koennen dir das aber auch nur mitteilen, wenn sie Deinen "offenen Port" kennen wuerden. Henne-Ei-Problem. An der Stelle bieten sich dann eine Online-Lobby - oder fixe TCP-Ports an. Die Onlinelobby hat den Vorteil, dass die "immer gilt" und nicht wie wechselnde IPs der Clients als unsicherer Kandidat anzusehen sind.
Du kennst vielleicht auch noch von Diablo2 die Abfrage von IPs im LAN-Spiel. Mit Warcraft 3 kam dann die Lobby - und ich habe das bei TVTower mittels "Broadcast" umgesetzt (geht nur mit IPv4) - sprich im Lan wird bspweise an x.x.x.255 geschickt - und alle angeschlossenen Geraete erhalten das Paket - nur die Clients interessieren sich dann dafuer ;-).

bye
Ron


Ersteller
Husi012
In den letzten 60 min online
Husi012
Rang 3

Projekte: 1
Designs: 0
Blogs: 2
Aktivität:
Aktiv
19.09.2015 - 11:57

Ok Danke.

Nochmal wegen dem Server bzw. Client. Ich weis nicht ob das mit anderen Programmiersprachen anders ist, hier kann man nur einem socket etwas schicken. Dadurch dann keine Ip. So wie ich es jetzt machen würde, wäre dann den Server schnell in ein Client umwandeln und dem eigentlichem Client der zum Server wird, wo dann die Ip angegeben wird. Dann sende ich etwas und wandel alles um.

Ist irgendwie seeehr umständlich. Aber ein Socket bekommt man ja nur dazu, wenn der connected


Ein Bug ist mehr als ein Bug.... es ist ein .... Feature.... ähh natürlich ein Käfer!!

Meine Eigene Seite: Hier klicken

GWRon
In den letzten 60 min online
GWRon
Rang 6

Projekte: 2
Designs: 3
Blogs: 7
Aktivität:
Sehr aktiv
19.09.2015 - 17:44

Wie du das loest, liegt an Deiner Programmiersprache.

Du sendest Daten - und irgendwer (anfaenglich der "server") empfaengt sie - und kann dann anhand der empfangenen Daten + Metainformationen dem Sender ein Paket zurueckschicken "hoer ma ... deine IP war X und dein Port Y". Von anderen Clients schickt er, der Server, die notwendigen Daren ebenfalls an den Client.

Die Clients selbst muessen nicht wissen wie ihre IP und ihr Port ist - nur die Gegenueber muessen es wissen (Zieladresse).

 

bye
Ron 


Ersteller
Husi012
In den letzten 60 min online
Husi012
Rang 3

Projekte: 1
Designs: 0
Blogs: 2
Aktivität:
Aktiv
20.09.2015 - 10:09

Hmm... Ich weis nicht ob ich was falsch gemacht habe, aber es geht nicht...


Ein Bug ist mehr als ein Bug.... es ist ein .... Feature.... ähh natürlich ein Käfer!!

Meine Eigene Seite: Hier klicken

GWRon
In den letzten 60 min online
GWRon
Rang 6

Projekte: 2
Designs: 3
Blogs: 7
Aktivität:
Sehr aktiv
20.09.2015 - 23:27

Deine Aussage ist nun wenig hilfreich.

 

Was hast Du denn genau umgesetzt?
- kontaktiert Client1 (bzw Client2, Client3 ...) erfolgreich den Server?
- registriert Client1 die Antworten vom Server (bspweise seine AbsenderIP/Port-Kombination, die Liste anderer verbundener Clients...)
- versuchst Du mit Client1 dann Client2 zu erreichen (was wohl fehlschlaegt)
- versucht Client2 sich mit Client1 zu verbinden (was klappen sollte, sofern Client1 schon den Versuch unternahm Client2 zu erreichen)

 

bye
Ron


1234