Winsock2-Verbindung über das Internet
-
Hiho.
Ich beschäftige mich seit kurzem ein wenig mit der Netzwerkprogrammierung und habe mir zur Übung erst einmal ein kleines Client-Serversystem geschrieben.
Diese Programme tun dabei nichts weiter als sich miteinander zu verbinden und bescheid zu sagen wenn dies geschehen ist.
(Also das eine fragt an (connect) und das andere wartet auf eine Anfrage (listen/accept)).Da ich jedoch nur einen Rechner hier rumstehen habe, habe ich zeuerst mal versucht die localhostIP anzugeben, danach dann die "echte" lokale IP meines Rechners und dies hat auch alles schön geklappt, weswegen ich jetzt einfach mal annehme, dass es auch auf verschiedenen Rechnern in einem funktionierendem lokalen Netzwerk funktioniert.
Meine Frage jetzt ist jedoch, wie stelle ich eine Verbindung über das Internet her?
Dabei nehmen wir einfach mal an ich kenne die InternetIP sowie die lokale IP des Netzwerks wo das Serverprogramm drauf ist sowie die InternetIP und lokale IP des Netzwerkes wo das Clientprogramm drauf ist.Hier ein Paar relevante Codestellen die über die Einstellungen Auskunft geben.
// Für Client und Server der gleiche Code WSAStartup(MAKEWORD(2, 0), &wsa); socket(AF_INET, SOCK_STREAM, 0); // SOCKADDR_IN sin_family = AF_INET; sin_port = htons(0445); // <-- der Port 445 ist bei mir offen, ist das so dann auch richtig angegeben? // Dies hier ist speziell für den Clienten sin_addr.S_un.S_addr = inet_addr("127.0.0.1 bzw 'echte' lokale IP"); // Dies hier ist speziell für den Server sin_addr.S_un.S_addr = ADDR_ANY;Wenn ich nämlihc für die IP in S_addr einfach die InternetIP verwende funktioniert das nicht, selbst auf dem Selben Rechner.
Was müsste ich jetzt also tun, damit ein Kolege von mir der auf seinem Rechner ein Clientprogramm hat, sich mit mit dem Server auf meinem Rechner verbinden kann?
Habe ich dafür nur "falsche Einstellungen"? Oder hat man dafür noch großartig mehr tu machen?
-
Frage Zwei:
Wenn Ich jetzt die InternetIP des Netzwerks als auch die lokale IP des Rechners dieses Netzwerks kenne, macht es dann ein Unterschied ob es sich jetzt um einen einzelnen Rechner handelt der direkt mit dem Internet verbunden ist oder ob es einer von vielen Rechnern an einem Router ist?
-
Dein Kollege müsste die IP deines Routers oder eben anschlusses in seinem client prog haben und du müsstest in deinem router (wenn du einen hast) den port auf deinen Server leiten.
/edit 2.Frage:
Client
|
|
Server
/ \
Server1 Server2Jetzt sagen wir der Client connectet auf den Server und ab hier beginnt ein lokales Netzwerk mit zwei servern jeder server hat einen http server installiert der auf port 80 läuft. Jetzt willst du mit dem Client die Server einzeln ansteuern. -> Geht nicht! weil pro ip nur einmal der jeweilige port und du hast nur eine ip nähmlich von Server.
Beantwortet das deine frage?
mfg tobZel
-
Dankö für die schnelle Antwort.
Falls du mit Port auf Server lenken meinst, auf den Rechner auf auf dem der Server läuft ist das doch wohl schon automatisch so wenn es nur einen Rechner gibt und der Port zudem frei ist oder?Also zu meinem Netzwerk.
Ich habe einen Router an dem ein einziger Rechner angeschlossen ist.
Mit XPclean habe ich nachgeschaut welche Ports offen sind und nicht durch meine Firewall geblock werden, dies war Port 445 (ist es dann korrekt ihn mit htons(0445) anzugeben?).
Meine InternetIP lautet 80.xxx.xxx.xxx (im folgenden mit 80 abgekürzt) und meine lokale IP lautet 192.xxx.xxx.xxx (im folgenden mit 192 abgekürzt).Mein Client kennt nun meine internetIP zu meinem Router sowie dessen offenem Port, welcher für den einzigen verfügbaren Rechner wohl erreichbar sein sollte.
Mein Server bindet den Port der auch im Clienten angegeben ist.
Wenn ich im Clienten die IP 127.0.0.1 angeben, also die IP meines lokalen Netzwerkes und beide Programm auf meinem Rechner ausführe klappt das.
Den Client mit der InternetIP zu meinem Netzwerk habe ich einem Freund gegebn.
Doch die Verbindung konnte nicht hergestellt werden.Ebenfalls versucht diese Clientversion von meinem Rechner aus wieder zu meinen Rechner zu verbinden.
Also Prinzipiell klappt das Programm ja, nur halt nicht über das Internet.
Mit AF_INET und SOCK_STREAM bestimme ich ja, dass die Verbindung über TCP aufgebaut werden soll.
Die Frage ist jetzt, muss dem dritten Parameter von "socket()" ein anderes Argument als 0 übergeben werden?
Denn in dem MSVS-Manual steht zwar:
Protocol to be used with the socket that is specific to the indicated address familyDoch sind da keine Möglichkeiten angegeben.
Sicherlich irgendwas mit TCP, doch wenn man nicht das Präfix kennt kann man das ja auch nicht angeben.Ansonsten könnte eigentlich nur noch
addr.sin_family = AF_INET; addr.sin_port = htons(0445); // ist 0445 korrekt wenn der Port 445 gemeint ist? addr.sin_addr.S_un.S_addr = inet_addr("80...");relevant sein.
addr ist dabei eine SOCKADDR_IN struktur.Beim Server sieht diese Stelle dann so aus:
addr.sin_family = AF_INET; addr.sin_port = htons(0445); addr.sin_addr.S_un.S_addr = ADDR_ANY;Wenn die Einstellungen die ich hier gezeigt habe korrekt sind, kann die Sache dann nur noch an Sachen liegen die vom Programm unabhängig sind (zum Beispiel feherhaftes Netzwerk oder falsch eingestelltes Portgedöns) oder gibt es andere "Einstellungen" die man zuvor treffen muss?
-
Ebenfalls versucht diese Clientversion von meinem Rechner aus wieder zu meinen Rechner zu verbinden.
um Missverständnissen aus dem Weg zu gehen, dies hat auch nicht geklappt.
-
Dein Kollege braucht deine lokale ip gar nicht zu wissen. Nur die ip deines routers im netz.
Gib trotzdem auch wenn du nur einen pc angeschlossen hast im router den port frei dort musst dann ja auch deine lokale ip angeben. Die meisten router denken gar nicht darüber nach ob nur ein rechner angeschlossen ist wenn jemand eine verbindung zu ihnen aufbaut gucken sie in der port freigabe tabelle nach dem port wenn sie ihn gefunden haben leiten sie die anfrage an den Netzwerk pc weiter dessen ip dort angegeben ist.mfg tobZel
-
Ui, dass Router das nicht automatisch machen wenn nur ein Rechner dran hängt wusste ich nicht.
Das hat zwar nun etwas gedauert bis ich herausgefunden habe wie man das macht (stand doch tatsächlich nicht im Handbuch des Routers
), doch nun habe ich einen Port auf meinen Rechner freigeben können und es klappt nun alles wie es soll, danke 
Aber was mache ich, wenn ich dieses Prinzip nun zum Beispiel auf ein Spiel anwenden möchte und immer wieder Nachrichten bezüglich Spielerposition oder Dergleichen verschicken möchte. Also das einer der Spieler die Rolle des Servers übernimmt und der Gegenspieler die des Clienten.
Da kann ich doch von den Spielern nicht verlangen: "Schaltet doch mal bitte Port xy frei".Gibt es dafür vielleicht so Standardports oder sowas?
Es gibt ja Spiele da braucht man lediglich die IP des anderen Spielers eingeben und es klappt dann einfach so, ohne dass man da an den Ports rummachen müsste(nun gut, dass man die IP selbst eingeben muss ist wohl nur bei älteren Spielen so, doch ändert das ja nichts daran, dass es sowas gibt oO).Auf jeden Fall danke für die Hilfe, hat mir sehr weiter geholfen.
-
Du stellst eine TCP verbindung vom spieler zum server her. Jetzt kann der Server doch über die verbindung auch dem Client was schicken da brauchst nicht nochmal ne verbindung!
mfg tobZel
-
Ja, das klappt ja auch.
Einen kleinen Konsolenchat habe ich auch schon hinbekommen und werde wohl auch nicht so große Probleme haben ein kleines Spielchen wie Pong oder Snake für 2 Spieler hinzubekommen.
Doch das Problem ist, das klappt jetzt speziell bei mir, weil ich den Port freigeschaltet habe.Zur Zeit mache ich auch einfach so weiter und setze einfach vor-raus(Bindestrich steht nur da,weil das Wort ansonsten zensiert würde oO), dass der Port den die Spieler angeben auch frei ist.
Doch wenn ich mich zurück erinnere, gab es doch Spiele bei denen man einfach nur die IP eingeben musste und der Host in der Funktion als Server nichts an den Ports machen musste oder irre ich mich da?
Wenn wir zum Beispiel das Spiel Star Craft betrachten (Ist hierfür zwar nicht das beste Beispiel doch das einzige das ich persönlich kenne, sprich gespielt habe und nicht auch auf einem Internetserver läuft).
Dort wählt man sich ja zuerst auf ein Internetserver ein, dem Battlenet.
Doch wenn jemand ein Spiel erstellt, ist der Spielhost der neue Server wenn man so will, jeder der sich da einloggt wird mit dem Host verbunden, auf dem Battlenetserver wird nicht gespielt.Doch bevor ich mit Starcraft spielen konnte musste ich ja auch nicht erst an den Ports rummachen.
-
Die Frage ist also, muss ich jetzt einfach damit leben, dass der Hostspieler den Port den er verwenden möchte selbst freischalten muss oder gibt es da einen anderen Weg bei dem man vielleicht auf diese Einstellerei verzichten kann?
-
if(0445 == 293) { std::cout << "Weltuntergang..."; }Tja... mach dich bereit!
-
Was willst du mir jetzt damit sagen?
-
Er will dir damit sagen, dass du das if () {} auch gleich weglassen kannst, es sei denn, du willst mir weiß machen, dass 445 gleich 293. Im übrigen wird vor(r)aus nur mit einem r geschriben, und wurde deshalb zensiert.
-
if(0445 == 293) { std::cout << "C++ kennt Oktalzahlen!" << std::endl; } if(445 == 293) { std::cout << "Sicher nicht!" << std::endl; }addr.sin_port = htons(0445); // ist 0445 korrekt wenn der Port 445 gemeint ist?Nein, ist es nicht, 445 ist 445, 0445 ist 293.
Wäre mir aber auch nicht aufgefallen...