Verbindungsproblem mit Sockets



  • Hallo,

    ich habe mit Hilfe des Tutorials auf www.c-worker.ch einen Client und einen Server erstellt.

    Client:

    #include <windows.h>
    #include <winsock2.h>
    #include <iostream>
    
    //Prototypen
    int startWinsock();
    long getAddrFromString( char* hostnameOrIp, SOCKADDR_IN* addr );
    
    int main( int argc, char** argv ) {
       long rc;
       SOCKET s;
       SOCKADDR_IN addr;
       char buf[256];
    
       if( argc < 2 ) {
          std::cout << "Usage: sock <hostname oder ip des servers>" << std::endl;
          return 1;
       }
    
       rc = startWinsock();
       if( rc != 0 ) {
          std::cout << "Fehler: startWinsock, fehler code: " << rc << std::endl;
          return 1;
       }
       else {
          std::cout << "Winsock gestartet!" << std::endl;
       }
    
       s = socket( AF_INET, SOCK_STREAM, 0 );
       if( s == INVALID_SOCKET ) {
          std::cout << "Fehler: Der Socket konnte nicht erstellt werden, fehler code: " << WSAGetLastError() << std::endl;
          WSACleanup();
          return 1;
       }
       else {
          std::cout << "Socket erstellt!" << std::endl;
       }
    
       memset( &addr, 0, sizeof( SOCKADDR_IN ) );
       addr.sin_family = AF_INET;
       addr.sin_port = htons(12345);
    
       rc = getAddrFromString( argv[1], &addr );
       if( rc == SOCKET_ERROR ) {
          std::cout << "IP für " << argv[1] << " konnte nicht aufgeloest werden!" << std::endl;
          closesocket( s );
          WSACleanup();
          return 1;
       }
       else {
          std::cout << "IP aufgeloest!" << std::endl;
       }
    
       rc = connect( s, (SOCKADDR*)&addr, sizeof( SOCKADDR ) );
       if( rc == SOCKET_ERROR ) {
          std::cout << "Fehler: connect gescheitert, fehler code: " << WSAGetLastError() << std::endl;
          closesocket( s );
          WSACleanup();
          return 1;
       }
       else {
          std::cout << "Verbunden!" << std::endl;
       }
    
       closesocket( s );
       WSACleanup();
    
       return 0;
    }
    
    //Funktionen
    int startWinsock() {
       WSADATA wsa;
       return WSAStartup( MAKEWORD( 2, 0 ), &wsa );
    }
    
    long getAddrFromString( char* hostnameOrIp, SOCKADDR_IN* addr ) {
       long rc;
       unsigned long ip;
       HOSTENT* he;
    
       if( hostnameOrIp == NULL || addr == NULL ) {
          return SOCKET_ERROR;
       }
       ip = inet_addr( hostnameOrIp );
       if( ip != INADDR_NONE ) {
          addr -> sin_addr.s_addr = ip;
          return 0;
       }
       else {
          he = gethostbyname( hostnameOrIp );
          if( he == NULL ) {
    	 return SOCKET_ERROR;
          }
          else {
    	 memcpy( &(addr -> sin_addr ), he -> h_addr_list[0], 4 );
          }
          return 0;
       }
    }
    

    Server:

    #include <windows.h>
    #include <winsock2.h>
    #include <iostream>
    
    //Prototypen
    int startWinsock();
    
    int main() {
       long rc;
       SOCKET acceptSocket;
       SOCKET connectedSocket;
       SOCKADDR_IN addr;
       char buf[256];
    
       rc = startWinsock();
       if( rc != 0 ) {
          std::cout << "Fehler: startWinsock, fehler code: " << rc << std::endl;
          return 1;
       }
       else {
          std::cout << "Winsock gestartet!" << std::endl;
       }
    
       acceptSocket = socket(AF_INET, SOCK_STREAM, 0 );
       if( acceptSocket == INVALID_SOCKET ) {
          std::cout << "Fehler: Der Socket konnte nicht erstellt werden, fehler code: " << WSAGetLastError() << std::endl;
          WSACleanup();
          return 1;
       }
       else {
          std::cout << "Socket erstellt!" << std::endl;
       }
    
       memset( &addr, 0, sizeof( SOCKADDR_IN ) );
       addr.sin_family = AF_INET;
       addr.sin_port = htons( 12345 );
       addr.sin_addr.s_addr = ADDR_ANY;
       rc = bind( acceptSocket, (SOCKADDR*)&addr, sizeof( SOCKADDR_IN ) );
       if( rc == SOCKET_ERROR ) {
          std::cout << "Fehler: bind, fehler code: " << WSAGetLastError() << std::endl;
          closesocket( acceptSocket );
          WSACleanup();
          return 1;
       }
       else {
          std::cout << "Socket an Port 12345 gebunden!" << std::endl;
       }
    
       rc = listen( acceptSocket, 10 );
       if( rc == SOCKET_ERROR ) {
          std::cout << "Fehler: listen, fehler code: " << WSAGetLastError() << std::endl;
          closesocket( acceptSocket );
          WSACleanup();
          return 1;
       }
       else {
          std::cout << "acceptSocket ist im listen Modus ..." << std::endl;
       }
    
       connectedSocket = accept(acceptSocket, NULL, NULL );
       if( connectedSocket == INVALID_SOCKET ) {
          std::cout << "Fehler: accept, fehler code: " << WSAGetLastError() << std::endl;
          closesocket( acceptSocket );
          WSACleanup();
          return 1;
       }
       else {
          std::cout << "Neue Verbindung wurde akzeptiert!" << std::endl;
       }
    
       closesocket( connectedSocket );
       closesocket( acceptSocket );
       WSACleanup();
    
       return 0;
    }
    
    //Funktionen
    int startWinsock() {
       WSADATA wsa;
       return WSAStartup( MAKEWORD( 2, 0 ), &wsa );
    }
    

    Wenn ich den Server jetzt auf meinem Computer starte und dann den Client mit 127.0.0.1 aufrufe, bekomme ich eine Verbindung zwischen Client und Server. Das ganze Funktioniert auch, wenn ich meine IP angebe, mit der ich im Internet bin.
    Was allerdings nicht funktioniert ist, wenn ich meinen Computer über ein LAN-Kabel mit einem anderen Rechner verbinde und auf meinem Computer den Server starte und auf dem anderen Rechner den Client mit meiner IP. Nach der Meldung des Clients, dass die IP aufgelöst sei, läuft das Programm noch kurz und bricht dann mit dem Fehler ab, dass der connect gescheitert ist.

    Kann mir jemand sagen, was ich falsch mache?

    Mit ratlosen Grüßen
    DerRatlose



  • Gib bei der Verbindung die interne Netzwerkadresse des Servers an, nicht die IP.

    Es sind ja nicht beide PC's mit dem Internet verbunden oder ?



  • Und wo soll ich die interne Netzwerkadresse des Server-Programms herbekommen?

    Mit ratlosen Grüßen
    DerRatlose



  • Gib in der Console ipconfig ein da solltest du dann bei IP-Adresse die Adresse sehen mit welche deinem PC zugeordnet wurde in dem Netzwerk.

    Oder irre ich mich da ??



  • Eine Verbindung sollte doch eigentlich auch über das Internet zustande kommen können, oder? Der Client wurde auf einem anderen Computer mit meiner Internet-IP gefüttert und hat folgendes Ergebnis geliefert (Die Ausgabe auf der Console):
    Windsock gestaretet!
    Wocket erstellt!
    Ip aufgeloest!
    Fehler: connect gescheitert, fehler code: 10060

    Laut einer Seite von Microsoft (http://support.microsoft.com/kb/819124/de):

    WSAETIMEDOUT (10060)

    * Übersetzung: eine Zeitüberschreitung trat bei Verbindung auf.
    * Description: ein Verbindungsversuch schlug fehl, da die verbundene Partei nicht korrekt nach einer Zeitspanne antwortete oder die hergestellte Verbindung fehlschlug, da der zu verbundene der Host sein Host nicht reagierte.

    Also funktioniert da immer noch nichts...
    Hat noch jemand eine Idee wie es funktionieren kann? Mach ich vielleicht einfach etwas falsch, oder müssen die Programme noch erweitert werden?

    Mit ratlosen Grüßen
    DerRatlose



  • Also sind beide PC's über einen Router mit dem Internet verbunden ?
    Wenn ja, dann musst du beim Router Forwoarding konfigurieren.
    Also die interne IP-Adresse des PC's mit dem Server und dem dazugehörigen Port den du benutzt eintragen. Damit weiß der Router welcher der PC's im Netzwerk der "Server" ist für denjenigen Port.



  • er hat von lokales netzwerk gesprochen...
    versuch mal den port in der firewall freizuschalten

    das hostauflösen funktioniert logischerweise, die ip wird ja schon angegeben, mehr als kopieren muss die funktion nicht mehr machen



  • DerRatlose schrieb:

    Was allerdings nicht funktioniert ist, wenn ich meinen Computer über ein LAN-Kabel mit einem anderen Rechner verbinde und auf meinem Computer den Server starte und auf dem anderen Rechner den Client mit meiner IP. Nach der Meldung des Clients, dass die IP aufgelöst sei

    Heißt das, Du nimmst ein Netzwerkkabel, steckst ein Ende in eine Netzwerkkarte an PC Eins und das andere Ende in eine Netzwerkkarte in PC Zwei?
    Ich glaube, das kann nicht funktionieren ...



  • Wieso sollte das nicht funktionieren? Wenn die Netzwerkkarten Auto-MDI(X) unterstützen, ist es völlig egal, ob noch ein Switch dazwischen hängt oder nicht.



  • Ich glaube, ich habe hier alles ein bisschen durcheinander geworfen...
    Zuerst hatte ich es so probiert, wie Belli beschrieben hat. Das hat nicht funktioniert. Dann habe ich einem Bekannten das Client-Programm gegeben. Während bei mir zu Hause das Server-Programm lief, hat er bei sich zu Hause das Client-Programm gestartet. Wir beide waren natürlich mit dem Internet verbunden. Allerdings hat das auch nicht funktioniert. In beiden Fällen kam keine Verbindung zu stande.
    Hoffentlich kann man jetzt nachvollziehen, was ich gemacht habe und besser zu einer Lösung kommen.

    Mit freundlichen Grüßen
    DerRatlose

    EDIT:

    McLove schrieb:

    Also sind beide PC's über einen Router mit dem Internet verbunden ?
    Wenn ja, dann musst du beim Router Forwoarding konfigurieren.
    Also die interne IP-Adresse des PC's mit dem Server und dem dazugehörigen Port den du benutzt eintragen. Damit weiß der Router welcher der PC's im Netzwerk der "Server" ist für denjenigen Port.

    Ja, die Rechner sind über einen Router mit dem Internet verbunden. Bin beim surfen im Internet auf diese Seite http://www.zfx.info/Tutorials.php?ID=84 gestoßen. Die Seite ist ein Tutorial zum erstellen eines Chatprogramms in der Konsole. Ganz unten auf der Seite steht dann was wegen Verbindungsschwierigkeiten wegen dem Router.
    Jetzt weiß ich, was McLove meinte. Aber muss man das nicht auch einfacher lösen können? Es muss doch irgendwie funktionieren, zwei Recher über das Internet zu verbinden, ohne die Routereinstellungen erst per Hand zu ändern. Oder irre ich mich da jetzt?



  • DerRatlose schrieb:

    Aber muss man das nicht auch einfacher lösen können? Es muss doch irgendwie funktionieren, zwei Recher über das Internet zu verbinden, ohne die Routereinstellungen erst per Hand zu ändern. Oder irre ich mich da jetzt?

    http://www.heise.de/security/Wie-Skype-Co-Firewalls-umgehen--/artikel/82054/0



  • Danke für den Link. Mit der Methode braucht man zwar ein bisschen Aufwand aber immerhin kann die Verbindung zu stande kommen. 👍

    Mit freundlichen Grüßen
    DerRatlose


Anmelden zum Antworten