TcpListener - Ungültige IP



  • Hallo!

    Ich habe folgenden Code für den Server:

    // Server.cpp: Hauptprojektdatei.
    #include "stdafx.h"
    using namespace System;
    using namespace System::IO;
    using namespace System::Net;
    using namespace System::Net::Sockets;
    using namespace System::Text;
    using namespace System::Threading;
    
    int main(array<System::String ^> ^args)
    {
    	Console::WriteLine("Server wird gestartet...");
    	try
    	{
    		Int32 port = 13000;
    		IPAddress^ localAddr = IPAddress::Parse(/*Die IP meines Computers (mit http://www.wieistmeineip.de/ herausgefunden)*/);
    		TcpListener^ server = gcnew TcpListener(localAddr,port);
    		server->Start();
    		...// hier steht weiterer Code
    	}
    	catch (Exception^ e) 
    	{
    		Console::WriteLine("Fehler! Der Server ist nun offline.");
    		Console::WriteLine("Genauere Informationen: " + e);
    		Console::ReadLine();
    	}
    	return 0;
    }
    

    Der Code wird zwar kompiliert, aber bei der Ausführung tritt folgender Fehler auf:
    System.Net.Sockets.SocketException (0x80004005): Die angeforderte Adresse ist in diesem Kontext ungültig
    bei System.Net.Sockets.Socket.DoBind(EndPoint endPointSnapshot, SocketAddress socketAddress)
    bei System.Net.Sockets.Socket.Bind(EndPoint localEP)
    bei System.Net.Sockets.TcpListener.Start(Int32backlog)
    bei System.Net.Sockets.TcpListener.Start()
    bei main(String[] args) in c:\users\<mein username>\docu
    ments\visual studio 2010\projects\neue projekte\ch
    at\version 1.0\server\server\server.cpp:Zeile 18.

    Kann mir jemand sagen mit welcher IP das funktioniert?
    Oder ist der Port falsch?
    Kann man vielleicht einen Server bei Nitrado mieten oder eine Netzwerkfestplatte verwenden?
    Info: Ich will ein Chat-Programm schreiben und das Programm mit meinem Freund benutzen.



  • Du kannst nicht auf deine oeffentliche IP (d.h. die, die du mit WhatsMyIP rausgefunden hast) binden. Dein Socket kann nur gegen eine Adresse gebunden werden, die dein Computer auch hat; von der oeffentlichen weiss der aber vermutlich nix. Der hat wohl eher eine 192.168.blah.blubb und erst hinterm Router wirds dann zu deiner oeffentlichen IP.

    Sprich: Du kannst nur gegen deine 192.168.blah.blubb binden (oder gegen eine Wildcard-Adresse, die gegen alle verfuegbaren IPs bindet) und musst dann auf deinem Router ein Port-Forwarding einrichten, dass er weiss, dass ankommende Verbindungen auf Port 13000 auf deinen Rechner weitergeleitet werden sollen.
    Es gibt aber auch ISPs, die Einkommende Verbindungen auf die Anschluesse ihrer Kunden von Haus aus blocken oder nicht-routebare IPs vergeben. In dem Falle muesstest du dir wirklich einen Server zulegen*. Da der dann gewoehnlich die IP, die du vom Hosting-Anbieter bekommst hat, kannst du sogar direkt gegen die binden :p

    Typische Frage, aber: Warum C++/CLI? Ist als Werkzeug gedacht, um Managed Code in Unmanaged Code und umgekehrt zu pressen, nicht zur normalen Anwendungsentwicklung.

    *: Empfehle ich nicht. Einen Server zu verwalten ist keine einfache Aufgabe und wenns jemand mal drauf schafft und damit Sachen anstellt bist du schuld, weil du ihn nicht richtig gesichert hast.



  • Hallo!

    Danke für die Antwort!
    Ich werde es mal mit Port-Forwarding versuchen. Habe mir eben ein Video angeschaut, muss es aber noch probieren.

    Jonas OSDever schrieb:

    Warum C++/CLI? Ist als Werkzeug gedacht, um Managed Code in Unmanaged Code und umgekehrt zu pressen, nicht zur normalen Anwendungsentwicklung.

    Nicht? Wie würdest Du es dann programmieren?
    (Später soll es eine Windows-Forms-Anwendung werden.)

    Sorry, wenn die Fragen und Antworten total dämlich sind.



  • Moritz H. schrieb:

    Jonas OSDever schrieb:

    Warum C++/CLI? Ist als Werkzeug gedacht, um Managed Code in Unmanaged Code und umgekehrt zu pressen, nicht zur normalen Anwendungsentwicklung.

    Nicht? Wie würdest Du es dann programmieren?

    Kommt ganz drauf an. Wenn du es in .NET schreiben willst, wuerde ich C# nehmen. Wenn du es wirklich in C++ machen willst, wuerde ich vermutlich mit Boost.ASIO hantieren (braucht aber etwas Einarbeitungszeit).

    Moritz H. schrieb:

    (Später soll es eine Windows-Forms-Anwendung werden.)

    http://www.c-plusplus.net/forum/263084-full



  • Hallo!

    Was bringt dann C++/CLI?
    Und wenn ich es unbedingt in C++/CLI machen will?



  • Moritz H. schrieb:

    Was bringt dann C++/CLI?

    Jonas OSDever schrieb:

    Ist als Werkzeug gedacht, um Managed Code in Unmanaged Code und umgekehrt zu pressen, nicht zur normalen Anwendungsentwicklung.

    C++/CLI ist wie schon gesagt eine Interopt Sprache. Wenn du ne Menge nativen code hast den du in managed Code verwenden willst (oder andersrum) kann C++/CLI da einfacher sein als PInvoke. Weil man halt einfach eine Wrapperklasse basteln kann die beides verwendet. Trifft aber hier ja nicht zu.

    Moritz H. schrieb:

    Und wenn ich es unbedingt in C++/CLI machen will?

    Dann lies dir bitte mal Windows Forms und Visual C++ MACHT KEINEN SINN! durch, und überleg dir ob du dir das wirklich antun willst. Da du gesagt hast dass es eine Forms Anwendung werden soll, kann ich dir nur raten auf C# umzusteigen. Ist etwas Umgewöhnung, aber deutlich leichter zu verwenden.



  • Hallo!

    Wie würdest Du das dann in C++ mit der TcpListener-Klasse als Konsolenanwendung programmieren? Oder gibt es in C++ gar nicht die TcpListener-Klasse, sondern nur in C++/CLI?



  • TcpListener ist Teil des .NET-Frameworks. Jede Sprache mit .NET-Anbindung kann sie also nutzen. Also C#, Visual Basic und auch C++/CLI, auch, wenn es in letzterer normalerweise wenig Sinn macht.

    In C++ hast du keinen TcpListener, der Standard kann (noch) nicht mal Netzwerk von Haus aus.
    Was du aber machen kannst ist andere Bibliotheken zu nutzen. Beispielsweise eben Boost, was auf den gaengisten Plattformen mit gaengigen Compilern funktioniert.

    Willst du schnell deinen Server zusammenschreibseln? Dann bleib bei .NET und steig auf C# um.
    Willst du deinen Server in C++ schreiben und bist bereit, auch ein wenig Zeit in die Einarbeitung mit ASIO zu investieren? Dann schnapp dir Boost nehm C++.
    Nur lass den C++/CLI-Gedanken fallen.



  • Danke! Jetzt sehe ich klarer. Mal ein Eintrag ohne diese Fachsprache 🙂

    Jetzt aber zurück zu meiner eigentlichen Frage: Welche IP muss man beim TcpListener - oder wie er dann auch heißen wird - nehmen?
    Und welche beim TcpClient?
    Die vom Router oder die vom PC? Oder eine Andere?

    Danke im Voraus



  • Also folgendes, meine Glaskugel hat durch die Funkkopfhoerer immer mal Stoersignale, aber ich hoffe mal, sie reicht noch soweit, um halbwegs dein Netzwerk-Setup zu erkennen.

    Im folgenden gehe ich davon aus, dass deine Maschine momentan ihre Adresse noch dynamisch kriegt und dass du einen Telekom-Speedport hast (sind umgelabelte Billigrouter aber die Firmware sieht zumindest aehnlich aus). Es kann also sein, dass die Anleitung hier nicht 100%ig auf dich zutrifft. Falls etwas offen bleibt oder bei dir anders funktioniert, fuehl dich frei, zu fragen.

    Insofern -- let's get dirty.

    Zunaechst einmal brauchst du die Windows-Adapter-Konfiguration. Druecke Win + R und geb dann ncpa.cpl ein. Anschliessend musst du deinen verbundenden Adapter finden. Ich weiss nicht, ob du ueber WLAN oder Ethernet verbunden bist; irgendein Adapter sollte jedenfalls verbunden sein.
    Jedenfalls klickst du mit rechts auf diesen und waehlst Status . Dort kannst du unter Details sehen, welche Adresse der Adapter momentan hat und ob DHCP aktiviert ist. Sofern du nichts umgekrempelt hast, duerfte DHCP wohl aktiviert sein und die Adresse 192.168.1.2 oder etwas aehnliches sein. 192.168.x.y ist ein privater Adressraum, d.h. diese Adressen werden nur hinter deinem Router vergeben (es gibt noch mehr solche Raeume, aber am einfachsten ist es wohl, vorerst bei diesem zu bleiben).
    Wichtig ist in deiner Adresse die Zahl x nach 192.168., denn die normale Netzwerk-Maske fuer die 192.168-er-Netze ist 255.255.255.0, d.h. du hast 255 Subnetze a 255 Adressen. Oder uebersetzt: 192.168.42.2 kann (unter Normalbedingungen) auf 192.168.42.5 zugreifen, nicht aber auf 192.168.43.2 oder 192.168.43.5. Es gibt Moeglichkeiten sowas zu verbinden, aber das fuehrt zu weit.
    Kurzum: Von 192.168.x.y praegst du dir erstmal das x ein. Anschliessend gehts in die Router-Konfiguration, im Beispiel hier also unter speedport.ip . Die Menues koennen unter anderen Routern anders heissen. Jedenfalls findest du unter Allgemeine Einstellungen auch die DHCP-Einstellungen . In meinem Fall kannst du dort auch die Adresse des Routers im LAN festlegen (was auch immer das unter DHCP zu suchen hat), wobei da auch irgendwas 192.168.x.y (y vermutlich 1) stehen sollte und das x mit deinem gemerkten uebereinstimmt. Praege dir diese gesamte Adresse ein, du brauchst sie noch! Fasse die Einstellung jedenfalls nicht an, sondern gucke, fuer welchen Bereich DHCP aktiviert ist. In meinem Fall ist (eher war) es fuer den gesamten Adressraum von 192.168.1.2 bis 192.168.1.255 aktiviert. Sofern du nicht 253 Geraete hast, ist das aber nicht sinnvoll. Begrenze den Adressraum, beispielsweise auf 192.168.x.2 bis 192.168.x.42.
    So, damit hast du dir in dem Falle erstmal ein paar Adressen freigeschaufelt. Back to Windows. In den hoffentlich noch geoeffneten Adaptereinstellungen suchst du dir den Adapter wieder raus, klickst diesmal auf Eigenschaften. Scroll unten runter, bis du Internet Protokoll Version 4 findest. Doppelklick drauf (nicht auf das Haekchen, du willst es nicht deaktivieren) und stelle folgendes ein: Zuerst manuelle IP-Vergabe ( Folgende IP-Adresse verwenden ), dann die IP auf irgendein 192.168.x.z festlegen, wobei z ausserhalb des DHCP-Bereichs liegt (0 und 255 darf es auch nicht sein, das haette spezielle Bedeutung). Wenn der DHCP-Bereich also beispielsweise von 2-42 geht, kannst du z zwischen 43 und 254 frei waehlen. Als Subnetz-Maske duerfte Windows 255.255.255.0 automatisch ergaenzen. Das Gateway musst du auf die Adresse vom Router setzen, also das, was du dir merken solltest. Als DNS-Server traegst du dieselbe Adresse ein.
    Damit waere der erste Schritt getan. Im Programm bindest du fortan gegen die festgelegte IP-Adresse (oder gegen sowas wie IPv4.Any).

    Als zweites solltest du in der Windows-Firewall den Port freigeben. Ich sehe du willst 13000 verwenden, also nehmen wir den als Beispiel. In der Windows-Firewall einfach unter den Eingehenden Regeln eine Port-Freigabe-Regel fuer TCP erstellen mit Port = 13000. Ich kann dir nicht genau sagen, wie das bei dir aussieht, weil ich nicht weiss, ob die FW-Config von Windows Server anders als die von den "normalen" Windows-Clients aussieht. Jedenfalls muesste die Regel dann noch aktiviert werden und alle Verbindungen zulassen.

    So, fasst geschafft. Jetzt noch einmal zum Router. Unter den Erweiterten Einstellungen nach Portzuordnungen suchen. Dort eine neue erstellen. Im Falle eines Speedports waeren die Parameter Benutzerdefiniert/TCP, Remote-Host freigelassen, Remote-Portnummernbereich auf 1300, Lokaler Host auf die festgelegte IP deines Computers (also z.B. 192.168.1.43) und der lokale Port als 13000. Status sollte selbstredend aktiviert sein.

    So, wenn jetzt also alles gut geht, solltest du deinen Server gegen deine eigene IP des Rechners hinterm Router binden und den Client gegen die IP von WasistmeineIP oder wie das Ding heisst.

    Also nochmal ein Example-Setup:
    Router: 192.168.1.1
    DHCP-Bereich: 192.168.1.2-192.168.1.42

    IP des Rechners: 192.168.1.43
    Gateway/DNS: Wie Router, also 192.168.1.1

    Firewall: 13000 eingehend von ueberall zulassen

    Router: Port 13000 von draussen nach 13000 drinnen durchschleusen (TCP)

    Server: Gegen 192.168.1.43/13000 binden.
    Client: Auf 1.2.3.4/13000 (WasIstMeineIP) connecten.

    Trouble-Shooting: Je nach Vertrag kann es sein, dass du Verbindungen von aussen gar nicht reinbekommst oder das erst vom ISP aktivieren lassen musst.
    Ausserdem wechselt deine IP bei jedem Router-Neustart (dass du ne statische hast ist unwahrscheinlich). Also musst du nach jedem Neustart deinem Kumpel die IP neu sagen. Oder irgendeinen DynDNS-Service in Anspruch nehmen.

    Ach ja: Netzwerksachen sind heikel, offene Ports noch mehr. Ich uebernehme keinerlei Gewaehrleistung, wenn was nicht mehr geht oder sich was auf deinem Rechner einnistet.

    So, hoffentlich hilft dir die Textwand etwas.



  • Danke erst mal für die Antwort!
    Ich habe sie noch nicht ausprobiert, weil sie ja - wie Du gesagt hast - nicht so sicher ist.
    Gibt es vielleicht eine sichere(re) Technik?
    Mit Kennwortschutz oder so? Oder vielleicht mit einem SslStream?
    http://msdn.microsoft.com/de-de/library/system.net.security.sslstream(v=vs.110).aspx



  • "Unsicher" bezog sich darauf, dass du dir mit nem von aussen erreichbaren offenen Port ne Luecke ins System reisst. Weniger der offene Port selbst ist das Problem, sondern der Dienst, der ihn verwendet; in dem Falle also dein Programm. Und das voellig unabhaengig von einem SslStream oder nicht.

    Je nach dem, wie gut oder schlecht das Ding dahinter ist, kann es ein Einfallstor sein oder eben nicht. Aber lass dir gesagt sein, es ist nicht einfach, sowas absolut sicher zu programmieren. Praktisch ueberall musst du die Validitaet der Daten verifzieren, um sicherzugehen, dass dein gegenueber nix anstellen kann. Schoenes Beispiel: Heartbleed. Wer mit 256 Bytes auf "Send me 256 Bytes of 'Blah'" antwortet, der schickt auch mal Daten uebers Netz, die da nicht raus sollen.
    Ebenso kannst du Angreifern ein Einfallstor bieten, wenn du nicht aufpasst. In .NET mag das durch die tausend Range-Checks und weiss der Geier was schwieriger sein, moeglich ist es aber trotzdem.

    Es sei gesagt, dass Port 13000 wohl eher nicht zu den Standard-Angriffsports gehoert und dass man schon recht gezielt angreifen muesste, um da wirklich was einzuschleusen. Service zum Absturz bringen duerfte noch eher gehen, aber naja.
    Was ich damit sagen will: Es ist moeglich, dass dich jemand angreift, wenn auch recht unwahrscheinlich. Mit dem letzten Satz im vorherigen Post wollte ich mich nur gegen Konsequenzen absichern, sollte tatsaechlich mal etwas passieren, auch wenn die Chance gering ist (sofern dein Freund dich nicht bewusst uebers Ohr hauen will :p ).

    EDIT: Mir faellt gerade noch ein: Du koenntest auch irgendeinen VPN-Tunneling-Srevice wie Hamachi nutzen. Das waere zumindest etwas sicherer, als sich routerseitig der ganzen Welt zu oeffnen



  • Danke, ich werde es mir mal überlegen.



  • Noch eine Frage: Ich könnte die Daten mit einem SslStream verschlüsseln, damit sie nicht jeder lesen kann, oder?



  • Jonas OSDever schrieb:

    Weniger der offene Port selbst ist das Problem, sondern der Dienst, der ihn verwendet; in dem Falle also dein Programm. Und das voellig unabhaengig von einem SslStream oder nicht.

    Kommt dranf an ob man Client-Zertifikate verwendet.



  • Laut folgender Internetseite braucht man für einen SSL-Stream nicht unbedingt ein Client-Zertifikat: http://support.microsoft.com/kb/907274/de
    Dort steht:
    Some of the misconceptions that we see on a regular basis are:

    • Client certificates are needed to make SSL work properly.

    ...



  • Ohne Client-Zertifikat kann man allerdings als Server nicht sagen ob man da verschlüsselt mit einem echten Nutzer spricht - oder ob man verschlüsselt mit einem Angreifer spricht.
    Zumindest sofern man da nicht noch andere Maßnahmen trifft 😉



  • Ich weiß, aber man könnte doch dann im SSL-Stream auf eine bestimmte Antwort warten z.B. ein Kennwort, oder?


Anmelden zum Antworten