Hilfe bei sockets benoetigt!



  • Hallo @ all,

    ich bin gerade dabei mich in die Welt der sockets einzuarbeiten, allerdings fehlt mir noch der richtige Durchblick 😕 . Wie eine normale Client- oder Server-socket Struktur aufgebaut ist, hab ich so weit verstanden, allerdings fehlt mir der Ansatz, wenn es darum geht eigene Funktionen zu schreiben und das sollte ja eigentlich Sinn der ganzen Sache sein. 🙂

    Ich habe hier mal 2 Socket-TCP Beispielaufgaben (für Server und Client) aus dem Netz abgeschrieben (leider ohne Lösungen) und wie gesagt fehlt mir der Durchblick wie ich diese Funktionen schreiben muss. Deshalb hoffe ich auf etwas Hilfe von euch damit ich mal einen Anfang habe und weiter machen kann.

    Ich danke schonmal recht herzlich!!!

    *******************************************************************************

    TCP-Serverprogramm:

    Schreibe eine Funktion server(int s) für ein TCP-Serverprogramm.

    Annahme: das Programm hat schon den Port, an dem es auf Anfragen wartet, an
    den Socket s gebunden und die listen()-Funktion (int listen(int s, int backlog)) aufgerufen. Der Socket s wird an die server()-Funktion übergeben.

    Die Funktion soll in einer Endlosschleife jeden Verbindungswunsch annehmne, für Clients aus dem Netz 134.96.0.0 den String "09.09.2005" an den kontaktierenden Host zurücksenden und die Verbindung schließen. Falls der Client nicht aus dem bez. Netz
    stammt, soll die Verbindung ohne Antwort geschlossen werden.

    *******************************************************************************

    TCP-Clientprogramm:

    Schreibe eine Funktion "int gettime(struct sockaddr_in *ap, char *buffer)
    für ein TCP-Clientprogramm, der einen daytime-Server an Port 13 kontaktiert.
    Die IP-Addresse des Servers steht schon im richtigen Format in der übergebenen
    sockaddr_in-Struktur. Die Attribute sin_family und sin_port müssen noch von
    gettime() gesetzt werden.

    Ein daytime-Server sendet, nachdem er kontaktiert wurde, sofort die einzeilige
    Antwort, die aus Datum und Uhrzeit besteht. Falls das telnet-Programmm verwendet
    wird, sieht die Ausgabe folgendermaßen aus:

    $ telnet localhost 13
    Trying 127.0.0.1...
    Connected to localhost.
    Escape character is '^]'.
    Wed Mar 9 09:59:59 2005
    Connection closed by foreign host.

    Die gettime()-Funktion soll die Uhrzeit des Systems in den übergebenen Puffer kopieren und den Puffer mit einem String-Ende abschließen. Es darf davon ausgegangen
    werden, dass der Aufrufer von gettime() genügend Speicherplatz für den Puffer reserviert hat.

    *******************************************************************************



  • so, nachm 2ten ma durchlesen geblickt was du willst 😉

    aber ich weiss nicht was das problem ist - da du ja client - server anwendungen verstehst. das mit dem bestimmten netz realisierst du mithilfe von dem rckgabewert der funktion accept int accept(int s, struct sockaddr *addr, int *addrlen);

    (des unterstrichene)

    einfach die adresse nach der subnet-mask überprüfen - dann hats sichs, das senden von strings dürfte ja auch kein problem sein.

    ansonsten icq: 146917483

    mfg blan



  • mein Problem ist einfach der Aufbau der Funktionen. Ich kenne diese Server/Client sockets nur so dass vorher schon alles definiert bzw. initalisiert ist und deshalb kaum Funktionen vorkommen die solche Aufgaben erfüllen, wie z.B.: in den Aufgaben oben. Kannst du mir vielleicht mal einen der beiden Funktionen grob aufstellen, damit ich verstehe was diese Funktion alles erhalten muss.

    Ich danke!!!!



  • hiho, also hab ma kurz was geproggt - funktioniert auch, is aber nicht optimal und irgendwie ne mischung aus c und c++ glaub ^^

    hier die beiden sources (client und server) - hab versuch die sache noch n bissel zu kommentieren.

    client.cpp

    #include <iostream>
    using namespace std;
    
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    
    #define SOCKET_ERROR   -1
    #define INVALID_SOCKET -1
    
    #define BUFFER_SIZE    4096
    
    bool client_recv(int socket,
    		string *text);
    
    int main(int    argc,
    	 char **argv)
    {
      int nSocket = 0;
    
        // Socket erstellen
        nSocket = socket(AF_INET, SOCK_STREAM, 0);
    
          // Abfrage ob Socket fehlerhaft
          if (nSocket == SOCKET_ERROR)
          {
            cerr << "Socket konnte nicht erstellt werden" << endl;
            return 1;
          }
    
          /* Connect-Optionen setzten,
             sin_addr.s_addr = Adresse auf der "gehört" werden soll
    	 sin_port = Port auf dem "gehört" werden soll
    	 sin_familie = Zu verwendende Familie (AF_UNIX, AF_INET, ...) */
          struct sockaddr_in str_saddy;
    
            str_saddy.sin_addr.s_addr = inet_addr("127.0.0.1");
            str_saddy.sin_port        = htons(6552);
            str_saddy.sin_family      = AF_INET;
    
        // Zu einem Rechner verbinden
        if (connect(nSocket, (sockaddr*)&str_saddy, sizeof(struct sockaddr_in)) == SOCKET_ERROR)
        {
          cerr << "Verbindung konnte nicht hergestellt werden" << endl;
          return 1;
        }
    
        string text;
    
          if (client_recv(nSocket, &text))
          {
            cout << "[Nachricht] " << text << endl;
          }
    
        close(nSocket);
    
      return 0;
    }
    
    bool client_recv(int socket,
    		string *text)
    {
      char caBuffer[BUFFER_SIZE];
      int nRecv = 0;
    
        nRecv = recv(socket, caBuffer, sizeof(caBuffer) - 1, 0);
    
          if (nRecv != INVALID_SOCKET)
          {
            caBuffer[BUFFER_SIZE] = '\0';
            *text = caBuffer;
    
    	return true;
          }
    
      return false;
    }
    

    server.cpp

    #include <iostream>
    #include <string>
    using namespace std;
    
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    
    #define SOCKET_ERROR   -1
    #define INVALID_SOCKET -1
    
    int client_send(int socket,
    		string text);
    
    int main(int    argc,
    	 char **argv)
    {
      int nSocket = 0;
    
        // Socket erstellen
        nSocket = socket(AF_INET, SOCK_STREAM, 0);
    
          // Abfrage ob Socket fehlerhaft
          if (nSocket == SOCKET_ERROR)
          {
            cerr << "Socket konnte nicht erstellt werden" << endl;
            return 1;
          }
    
        /* Socket Option 'SO_REUSEADDR' setzten,
           damit der Port bei fehlerhaftem beenden nicht blockiert */
        {
          // Option aktivieren (0 = aus, 1 = ein)
          int opt = 1;
    
            if (setsockopt(nSocket, SOL_SOCKET, SO_REUSEADDR, (char*) &opt, sizeof(opt)) == SOCKET_ERROR)
            {
              cout << "Socket hat die Option 'SO_REUSEADDR' nicht erkannt" << endl;
            }
        }
    
          /* Bind-Optionen setzten,
             sin_addr.s_addr = Adresse auf der "gehört" werden soll
    	 sin_port = Port auf dem "gehört" werden soll
    	 sin_familie = Zu verwendende Familie (AF_UNIX, AF_INET, ...) */
          struct sockaddr_in str_saddy;
    
            str_saddy.sin_addr.s_addr = inet_addr("127.0.0.1");
            str_saddy.sin_port        = htons(6552);
            str_saddy.sin_family      = AF_INET;
    
        // Port an Socket binden
        if (bind(nSocket, (sockaddr*)&str_saddy, sizeof(struct sockaddr_in)) == SOCKET_ERROR)
        {
          cerr << "Socket konnte nicht gebindet werden" << endl;
          return 1;
        }
    
        // Server in listen-Modus setzten
        if (listen(nSocket, 3) == SOCKET_ERROR)
        {
          cerr << "Socket konnte nicht in 'listen'-Modus geschaltet werden" << endl;
          return 1;
        }
    
        // Endlose Warteschleife für alle eingehenden Verbindungen
        do
        {
          struct sockaddr_in str_client;
          socklen_t client_size = sizeof(sockaddr_in);
    
          int nClient = accept(nSocket, (sockaddr*)&str_client, &client_size);
    
            if (nClient == INVALID_SOCKET)
            {
              cerr << "Verbindung zum Client verloren" << endl;
            }
            else
            {
              string client_ip = inet_ntoa(str_client.sin_addr);
    
              cout << "[" << client_ip << "] Verbindung aktzeptiert" << endl;
    
    	    if (client_send(nClient, "hello world") == INVALID_SOCKET)
    	    {
    	      cerr << "[" << client_ip << "] Nachricht konnte nicht gesendet werden" << endl;
    	    }
    
              cout << "[" << client_ip << "] Verbindung beendet" << endl;
              close(nClient);
            }
        }while(true);
    
      close(nSocket);  
    
      return 0;
    }
    
    int client_send(int socket,
    		string text)
    {
      return send(socket, text.c_str(), text.length(), 0);
    }
    

    ansonsten nochmal nachfragen!

    mfg blan



  • danke erstmal für deine Bemühungen!!!

    wenn ich das richtig verstehe, sind dein client und server ein komplettes Programm, was mich wieder etwas verwirrt, da ich ja spezielle Funktionen für so ein Programm erstellen will. Wie stelle ich denn jetzt z.B: die Server Funktion server(int s) auf?

    Also ich bekomme s übergeben und soll in einer Endlosschleife jeden Verbindungswunsch annehmen, für Clients aus dem Netz 134.96.0.0 den String "09.09.2005" an den kontaktierenden Host zurücksenden und die Verbindung schließen. Falls der Client nicht aus dem bez. Netz
    stammt, soll die Verbindung ohne Antwort geschlossen werden.

    int accept(int s, struct sockaddr *addr, int *addrlen)
    {

    wenn das netz stimmt, dann

    nur einen string(09.09.2005) zurücksenden und dann schließen?

    ansonsten

    nur schließen?
    }

    welchen rückgabewert brauche ich für die server Funktion und umschließt diese dann die accept Funktion?
    😕 brauch wohl hilfe beim code erstellen 😞

    hoffe auf weitere Erklärungen 🙂



  • hi,

    kein problem - eine server-funktion ?

    mach in die server-funktion einfach alles server-spezifische rein (bind, listen und accept)

    und wenn du eine client-funktion willst machste dort alle client-spez. funktionen rein - das ist hier egtl nur connect.

    mfg blan



  • blan schrieb:

    hi,

    kein problem - eine server-funktion ?

    mach in die server-funktion einfach alles server-spezifische rein (bind, listen und accept)

    und wenn du eine client-funktion willst machste dort alle client-spez. funktionen rein - das ist hier egtl nur connect.

    mfg blan

    Also ich blick da noch nicht wirklich durch 😞

    bezogen auf die Aufgabe:
    bind und listen brauche ich doch dort nicht, oder?

    Kannst du mir vielleicht mal den strukturellen Aufbau dieser server(int s) Funktion zeigen?

    ich stelle mir das im Moment so vor:

    int server(int s) {

    int accept (int s, struct sockaddr * restrict addr ,
    socklen_t * restrict addrlen ) {

    .....
    }

    }

    was brauche ich alles noch und wo kommt diese Endlosschleife hin?

    am Beispiel würd ich es, glaube ich am besten verstehen, das gilt auch für die client Funktion. 🙂

    hoffe sehr auf weitere Erklärungen!!!

    danke!!!



  • hi,

    also wenn deine funktion int server(int s) client-verbindungen annehmen soll und denen eine nachricht senden soll und zum schluss die verbindung getrennt werden soll sieht die so aus

    int server(int nSocket)
    {
      do
      {
        struct sockaddr_in str_client;
        socklen_t client_size = sizeof(sockaddr_in);
    
        int nClient = accept(nSocket, (sockaddr*)&str_client, &client_size);
    
          if (nClient == INVALID_SOCKET)
          {
            cerr << "Verbindung zum Client verloren" << endl;
          }
          else
          {
            string client_ip = inet_ntoa(str_client.sin_addr);
    
    	cout << "[" << client_ip << "] Verbindung aktzeptiert" << endl; 
    
    	  if (client_send(nClient, "hello world") == INVALID_SOCKET)
    	  {
    	    cerr << "[" << client_ip << "] Nachricht konnte nicht gesendet werden" << endl; 
    	  }
    
    	cout << "[" << client_ip << "] Verbindung beendet" << endl; 
    	close(nClient);
          }
      }while(true);
    
      return 0; // keine ahnung wozu du ein return brauchst...
    }
    

    mfg blan



  • super, danke!!

    eine Frage hätt ich dann noch zu dieser Funktion und zwar wegen der Antwort für Clients aus dem Netz 134.96.0.0 . Also dort wo du im code "Verbindung akzeptiert" stehen hast, kommt da das Datum rein? Und wie implementiere ich diese Netzabfrage?

    wenn du mir jetzt noch beim client helfen könntest, könnte ich weiter testen und würd dich nicht mehr belästigen 😉

    int gettime(struct sockaddr_in *ap, char *buffer)

    ???struct sockaddr_in str_saddr;

    str_saddr.sin_port = htons(13);
    str_saddr.sin_family = AF_INET;

    ???

    danke nochmal!!!



  • also um das netz abzufragen holst du dir einfach die ip-adresse in dotierter schreibweise und splittest diese nach jedem punk -> dann einfach die einzelteile vergleichen. bei meiner funktion findest du die client ip in der variable client_ip 😉

    was willst du bei dem client noch genau wissen?

    mfg blan



  • ok danke das mit der Server Funktion hab ich jetzt hoffentlich verstanden.

    Beim Client ist mir immer noch der Aufbau schleierhaft, was alles in die Funktion muss und wie das mit dem buffer funktioniert.



  • ehm.. wieso is dir schleierhaft was da rein muss, wie du gesehn hast hab ich auch nur n teil aus der server.cpp in die funktion int server(int nSocket) reingetan.

    die recv funktion schreibt die daten die ankommen einfach nur in den buffer den du dann auslesen kannst. versteh net ganz was genau unklar ist.

    mfg blan



  • achso "copy and paste" 😃 dann bastel ich mal da jetzt dran rum und geh dann mit rauchendem Kopf ins Bett. 🙂

    Danke nochmal für die vielen Tipps!!! 👍


Anmelden zum Antworten