Sockets / Ports



  • Hallöle!

    So ich wagte mich nun etwas in die Netzwerkprogrammierung und war erst mal begeistert wie "einfach" dieses Client-Server-Modell srukturiert ist!
    Natürlich weiß ich, dass das ja aber auch nur der Anfang ist, und dass alles noch viel viel komplizierter werden wird (steht so zumindest in meinem Buch!).

    Jedoch habe ich noch ein paar grobe Verständnisprobleme mit den Sockets und ihrem Verhältnis gegenüber den Ports:

    Client-Programm:

    #include <windows.h>
    #include <winsock2.h>
    #include <stdio.h>
    #include <iostream>
    
    using namespace std;
    
    //Prototypen
    int startWinsock(void);
    
    int main()
    {
      long rc;
      SOCKET s;
      SOCKADDR_IN addr;
      char buf[256];
    
      // Winsock starten
      rc = startWinsock();
      if(rc != 0)
      {
        cout << "Fehler: startWinsock, fehler code: %d\n" << rc;
        return 1;
      }
      else
      {
        cout << "Winsock gestartet!\n";
      }
    
      // Socket erstellen
      s = socket(AF_INET, SOCK_STREAM, 0);
      if(s == INVALID_SOCKET)
      {
        cout << "Fehler: Der Socket konnte nicht erstellt werden, fehler code: %d\n" << WSAGetLastError();
        return 1;
      }
      else
        cout << "Socket erstellt!\n";
    
      // Verbinden
      memset(&addr, 0, sizeof(SOCKADDR_IN)); // zuerst alles auf 0 setzten
      addr.sin_family = AF_INET;
      addr.sin_port = htons(12345); // wir verwenden mal port 12345
      addr.sin_addr.s_addr = inet_addr("127.0.0.1"); // zielrechner ist unser eigener
    
      rc = connect(s, (SOCKADDR*)&addr, sizeof(SOCKADDR));
      if(rc == SOCKET_ERROR)
      {
        cout << "Fehler: connect gescheitert, Fehler code: %d\n" << WSAGetLastError();
          system("pause>nul");
        return 1;
      }
      else
        cout << "Verbunden mit 127.0.0.1..\n";
    
      // Daten austauschen
      while(rc != SOCKET_ERROR)
      {
        cout << "Zeichenfolge eingeben [max 256]: ";
        gets(buf);
        send(s, buf, strlen(buf), 0);
        rc = recv(s, buf, 256, 0);
        if(rc == 0)
        {
          cout << "Server hat die Verbindung getrennt..\n";
         break;
        }
        if(rc == SOCKET_ERROR)
        {
          cout << "Fehler: recv, fehler code: %d\n" << WSAGetLastError();
         break;
        }
        buf[rc]= '\0';
        cout << "\nServer antwortet: %s\n" << buf;
      }
      closesocket(s);
      WSACleanup();
     return 0;
    }
    
    int startWinsock(void)
    {
      WSADATA wsa;
     return WSAStartup(MAKEWORD(2,0),&wsa);
    }
    

    Serverprogramm:

    #include <windows.h>
    #include <winsock2.h>
    #include <stdio.h>
    #include <iostream>
    
    using namespace std;
    
    //Prototypen
    int startWinsock(void);
    
    int main()
    {
      long rc;
      SOCKET acceptSocket;
      SOCKET connectedSocket;
      SOCKADDR_IN addr;
      char buf[256];
      char buf2[300];
    
      // Winsock starten
      rc = startWinsock();
      if(rc != 0)
      {
        cout << "Fehler: startWinsock, fehler code: %d\n" << rc;
       return 1;
      }
      else
        cout << "Winsock gestartet!\n";
    
      // Socket erstellen
      acceptSocket = socket(AF_INET, SOCK_STREAM, 0);
      if(acceptSocket == INVALID_SOCKET)
      {
        cout << "Fehler: Der Socket konnte nicht erstellt werden, fehler code: %d\n" << WSAGetLastError();
       return 1;
      }
      else
        cout << "Socket erstellt!\n";
    
      // Socket binden
      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)
      {
        cout << "Fehler: bind, fehler code: %d\n" << WSAGetLastError();
       return 1;
      }
      else
        cout <<"Socket an port 12345 gebunden\n";
    
      // In den listen Modus
      rc = listen(acceptSocket,10);
      if(rc == SOCKET_ERROR)
      {
        cout << "Fehler: listen, fehler code: %d\n" << WSAGetLastError();
       return 1;
      }
      else
        cout << "acceptSocket ist im listen Modus....\n";
    
      // Verbindung annehmen
      connectedSocket = accept(acceptSocket, NULL, NULL);
      if(connectedSocket == INVALID_SOCKET)
      {
        cout << "Fehler: accept, fehler code: %d\n" << WSAGetLastError();
       return 1;
      }
      else
        printf("Neue Verbindung wurde akzeptiert!\n");
    
      // Daten austauschen
      while(rc != SOCKET_ERROR)
      {
        rc = recv(connectedSocket, buf, 256, 0);
        if(rc == 0)
        {
          cout << "Server hat die Verbindung getrennt..\n";
         break;
        }
        if(rc == SOCKET_ERROR)
        {
          cout << "Fehler: recv, fehler code: %d\n" << WSAGetLastError();
         break;
        }
        buf[rc] = '\0';
        cout << "Client sendet: %s\n" << buf;
        sprintf(buf2, "Du mich auch %s", buf);
        rc = send(connectedSocket, buf2, strlen(buf2), 0);
      }
      closesocket(acceptSocket);
      closesocket(connectedSocket);
      WSACleanup();
     return 0;
    }
    
    int startWinsock(void)
    {
      WSADATA wsa;
      return WSAStartup(MAKEWORD(2,0), &wsa);
    }
    

    Das bekannte und typische Anfänger-Tutorial zur Socketprogrammierung.
    Nun meine Fragen:

    Wieso werden hier Ports erfunden wie "12345" und wieso läuft das Ganze dann auch noch?? Soweit ich weiß benötigt man in so einem Falle doch den Port 80, oder???

    Jetzt möchte ich das Ganze mal übers I-net laufen lassen. Dann muss ich doch die IP 127.0.0.1 in meine IP (Beispiel 84.158.13.7) umschreiben, oder?
    Aber damit ist es dann doch nicht getan, oder? Wenn ich mit einem Kumpel chatten wollte, dann reicht es doch nicht, wenn ich die IP so umwandle und ihm dann das Clientprogramm schicke, oder? Was muss ich da umschreiben und was genau muss ich mit dem Serverprogramm machen?

    Woher weiß das Clientprogramm, dass es meinem Serverprogramm etwas schicken muss? Mein Serverprogramm beinhaltet nirgends irgendwelche IP-infos, sondern lediglich die Portnummer 12345. Aber im Internet gibts doch tausende von Servern...woher weiß dann das Clientprogramm, dass es zu meinem Serverprogramm muss?? Ich werde daraus noch nicht ganz schlau!

    Hm..hoffentlich habe ich jetzt niemanden verwirrt mit diesen Fragen 😕

    Naja auf Hilfe für diese Fragen wäre ich wirklich sehr sehr dankbar!!
    Ich denke wenn ich das Grundprinzip, an welchem ich hier offensichtlich noch scheitere, erst mal verstanden habe, dann fällt mir das Netzwerkprogrammieren wesentlich leichter!
    Viele Grüße
    Gapa



  • Gapa schrieb:

    Wieso werden hier Ports erfunden wie "12345" und wieso läuft das Ganze dann auch noch?? Soweit ich weiß benötigt man in so einem Falle doch den Port 80, oder???

    Es gibt ~65.000 Ports, wovon unter den ersten paar tausend ein paar eine Standard-Belegung haben, z.B. Port 80 für HTTP. Sogesehen kannst du die Ports nutzen die du willst, solange der Client den Server auf dem Port anspricht, auf dem dieser lauscht.

    Gapa schrieb:

    Jetzt möchte ich das Ganze mal übers I-net laufen lassen. Dann muss ich doch die IP 127.0.0.1 in meine IP (Beispiel 84.158.13.7) umschreiben, oder?
    Aber damit ist es dann doch nicht getan, oder? Wenn ich mit einem Kumpel chatten wollte, dann reicht es doch nicht, wenn ich die IP so umwandle und ihm dann das Clientprogramm schicke, oder? Was muss ich da umschreiben und was genau muss ich mit dem Serverprogramm machen?

    Der Server muss keine IP wissen, er lauscht einfach auf dem PC, auf dem er läuft, auf einem bestimmten Port. Der Client muss sich dann mit dem Server verbinden, muss also dessen IP und den Port wissen. Übers Internet geht das prinzipiell genauso, es sei denn der Server sitzt hinter einem Router, dann musst du den entsprechenden Port "forwarden".

    Gapa schrieb:

    Woher weiß das Clientprogramm, dass es meinem Serverprogramm etwas schicken muss? Mein Serverprogramm beinhaltet nirgends irgendwelche IP-infos, sondern lediglich die Portnummer 12345. Aber im Internet gibts doch tausende von Servern...woher weiß dann das Clientprogramm, dass es zu meinem Serverprogramm muss?? Ich werde daraus noch nicht ganz schlau!

    Hehe, das ist eigentlich ganz einfach 🙂 Der Programmierer des Client-Programms muss natürlich beim Programmieren entscheiden, wann wie wo verbunden und kommuniziert werden soll. Wenn dein Browser z.B. den HTML-Code einer Webseite runterladen will, sucht es sich die IP zu der von dir eingegebenen Adresse und schickt eine Nachricht hin, die irgendwo im HTTP-Protokoll spezifiziert ist. Der Server lauscht halt auf Verbindungen, merkt dass ein Client sich verbindet und er bekommt eine Nachricht. Seinerseits schickt er dann die HTML-Seite zurück.



  • Badestrand schrieb:

    Gapa schrieb:

    Jetzt möchte ich das Ganze mal übers I-net laufen lassen. Dann muss ich doch die IP 127.0.0.1 in meine IP (Beispiel 84.158.13.7) umschreiben, oder?
    Aber damit ist es dann doch nicht getan, oder? Wenn ich mit einem Kumpel chatten wollte, dann reicht es doch nicht, wenn ich die IP so umwandle und ihm dann das Clientprogramm schicke, oder? Was muss ich da umschreiben und was genau muss ich mit dem Serverprogramm machen?

    Der Server muss keine IP wissen, er lauscht einfach auf dem PC, auf dem er läuft, auf einem bestimmten Port. Der Client muss sich dann mit dem Server verbinden, muss also dessen IP und den Port wissen. Übers Internet geht das prinzipiell genauso, es sei denn der Server sitzt hinter einem Router, dann musst du den entsprechenden Port "forwarden".

    Ev. muss auf dem Server der Port auf eine entsprechende IP Adresse gebunden werden (bind). So können spezifische Adapter bzw. IP Adressen benutzt werden.

    Funktioniert auch ohne, aber man kann wenn man es benötigt. :-))

    Gruss Simon


Anmelden zum Antworten