socket send() und recv() dynamisch machen?

Dieses Thema im Forum "C/C++" wurde erstellt von blacky, 12.10.2009.

  1. blacky

    blacky Doppel-As

    Dabei seit:
    25.07.2006
    Beiträge:
    132
    Zustimmungen:
    0
    Hallo,
    ich hantiere ein wenig mit sockets und habe bereits erfolgreich mit TCP und UDP Daten versendet. :)) Leider stört mich, dass ich es bis jetzt beispielsweise bei einer TCP Verbindung nur geschafft habe, das der Client eine anfrage stellt und der Server diese beantwortet oder nur empfängt. Sprich, man hat immer den Ablauf Senden->Empfangen->Senden->Empfangen. Nun soll es aber dynamisch sein, sodass der Client z.B. zwei mal etwas sendet und so der Server auch zweimal etwas empfangen muss bzw. auch umgekehrt. Dies würde ja normalerweise bedeuten, dass es im Client zweimal "send()" und beim Server zwei mal "recv()" hintereinander gibt, aber das wäre ja wieder statisch. Ein Beispiel für das Verhalten welches ich programmieren will wäre ein Chat wo weder Server noch Client weiß wie oft empfangen bzw. gesendet werden muss. Ich habe bereits von "select()" gehört wo mehrere sockets und Clients überwacht werden, aber darauf will ich nicht hinaus. Ich möchte nur, dass der Server oder der Client so oft senden kann wie sie wollen. Ist dies mit "select()" doch möglich und wenn ja, wie? Ein paar Codebeispiele wären super.
    Danke im voraus!
     
  2. Anzeige

    Schau dir mal diese Kategorie an. Dort findest du bestimmt etwas.
    Registrieren bzw. einloggen, um diese und auch andere Anzeigen zu deaktivieren
  3. #2 bytepool, 12.10.2009
    Zuletzt bearbeitet: 13.10.2009
    bytepool

    bytepool Code Monkey

    Dabei seit:
    12.07.2003
    Beiträge:
    791
    Zustimmungen:
    0
    Ort:
    /home/sweden/göteborg
    Hi,

    prinzipiell wuerde ich dir empfehlen einfach mal ein Netzwerk tutorial durchzuarbeiten, oder dir mal den source code von einem kleinen Chat Programm oder so anzugucken. Das Thema ist einfach zu umfangreich, da kann man sich hier sonst die Finger zu wund schreiben, es gibt so viele verschiedene Moeglichkeiten und Techniken...

    Aber ganz grundlegend, einen Server implementierst du haeufig, indem du eine Endlos-Schleife um select() schreibst, mit der du eingehende Verbindungen abfaengst, die dann in eigenen Threads weiterverarbeit werden. Das ist eine von vielen Moeglichkeiten. Select solltest du dir auf jeden Fall angucken.

    Wenn dir blocking und non-blocking calls noch nichts sagen (bzw. synchrones vs. asynchrones Programmieren), solltest du dich auch da ein wenig einarbeiten.

    Code-Beispiele gibt es im Netz zuhauf.

    mfg,
    bytepool
     
  4. blacky

    blacky Doppel-As

    Dabei seit:
    25.07.2006
    Beiträge:
    132
    Zustimmungen:
    0
    erster Erfolg :)

    Hi, danke nochmal für die Antwort!
    Nun habe ich das Verhalten erreicht, dazu habe ich mir einen mini UDP Chat angeschaut, der mit "select()" bestückt war. Ehrlich gesagt habe ich den Code teilweise übernommen, darum bitte ich um Erklärung warum es "FD_SET(0, &fdsets)" gibt? Zudem wären noch Verbesserungsvorschläge super. Außerdem muss ich hierzu noch sagen, obwohl es wie ein Chat ausschaut möchte ich darauf nicht hinaus, sondern ich wollte mich mit dem Server verbinden und diesem Befehle geben und wenn sich ein Status im Server ändert soll er sich beim Client melden.
    Hier der komplette funktionierende Code:
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netdb.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <unistd.h>
    #include <string.h>
    #include <errno.h>
    #include <signal.h>
    #include <sys/fcntl.h>
    #include <sys/time.h>
    
    /*
     * 
     */
    
    void handler(int c)
    {
        fd_set fdsets;
        char buffer[1024];
        int max, bytes;
        while(1)
        {
           FD_ZERO(&fdsets);
           FD_SET(c, &fdsets);
           FD_SET(0, &fdsets);   //<- dies will ich wissen
           max = c;
           select(max + 1, &fdsets, NULL, NULL, NULL);
           if (FD_ISSET(c, &fdsets))
           {
               bytes = recv(c, buffer, sizeof(buffer)-1,0);
               buffer[bytes] = '\0';
               printf("Received: %s\n", buffer);
           }
           else if (FD_ISSET(0, &fdsets))
           {
               fgets(buffer, 1024, stdin);
               send(c, buffer, strlen(buffer),0);
           }
        }
    }
    
    int main(int argc, char** argv) {
    
        int client, sock, cli_size;
        struct sockaddr_in srv, cli;
    
        if ( (sock = socket(AF_INET, SOCK_STREAM, 0)) < 0 )
        {
            printf("Error creating socket");
            return -1;
        }
    
        srv.sin_addr.s_addr = INADDR_ANY;
        srv.sin_family = AF_INET;
        srv.sin_port = htons(9999);
    
        if ((bind(sock, (struct sockaddr*) &srv, sizeof(srv)))  < 0 )
        {
            printf("Unable to bind the socket");
            return -1;
        }
    
        if ((listen(sock, 3)) <0)
        {
            printf("Unable to start listening");
            return -1;
        }
        cli_size = sizeof(cli);
        client = accept(sock, (struct sockaddr*) &cli, &cli_size);
    
        handler(client);
    
        return (EXIT_SUCCESS);
    }
    
    Der Server läuft nun so, dass man sich mit telnet verbinden kann und von telnet sowie von dem Server selbst aus Nachrichten schreibt.
     
  5. #4 bytepool, 13.10.2009
    Zuletzt bearbeitet: 13.10.2009
    bytepool

    bytepool Code Monkey

    Dabei seit:
    12.07.2003
    Beiträge:
    791
    Zustimmungen:
    0
    Ort:
    /home/sweden/göteborg
    Hi,

    ein kurzes googlen schickte mich auf diese Seite:
    http://linux.die.net/man/3/fd_set

    Dort steht u.a. dass fd 0 der file descriptor fuer stdin ist, womit sich der Code doch eigentlich selbst erklaert.

    Select lauscht auf stdin (fd 0) und auf dem gegebenen Socket (fd c), und wenn von einem der beiden gelesen werden kann, werden beide Faelle der Reihe nach abgearbeitet. Wenn etwas vom Socket gelesen werden kann, wird es gelesen und auf stdout ausgegeben, und wenn etwas auf stdin geschrieben wurde, wird das gelesen und ueber die Verbindung fd c geschickt.

    Das einzige was mir auf Anhieb auffaellt, ist dass ich den file descriptor in handler() etwas aussagekraeftiger als "c" benennen wuerde. Ansonsten finde ich den Code eigentlich angenehm einfach und gut zu lesen. Aber ich bin weder ein C noch ein Netzwerk Wizard. ;)

    Edit:
    Naja, in deinem Beispiel Code fehlen natuerlich noch eine Menge Kontrollen, z.B. wirst du so Daten verlieren, wenn nach einem Durchlauf von select mehr als 1024 byte auf dem Socket angekommen sein sollten. <edit2> Ach nee, nicht unbedingt, der Rest wird dann mit etwas Glueck im naechsten select Durchlauf gelesen. </edit2> Da muesste dann noch einmal eine Schleife her. Aber wie das genau gehandhabt werden muss, haengt natuerlich auf von den Daten ab die du da rueber schickst, und ob es denn jetzt UDP oder TCP ist.

    Du darfst dich z.B. auch nicht darauf verlassen, dass byte chunks die du auf dem socket server verschickst, als einzelne chunks auf der anderen Seite wieder rauskommen. Es ist durchaus moeglich das 2 Pakete in einem select Durchlauf ankommen. Es gibt ein paar von diesen Kleinigkeiten auf die man achten muss, aber das haengt wie gesagt auch vom konkreten Programm ab.

    mfg,
    bytepool
     
  6. Anzeige

    Vielleicht findest du HIER Antworten.
    Registrieren bzw. einloggen, um diese und auch andere Anzeigen zu deaktivieren
Thema:

socket send() und recv() dynamisch machen?

Die Seite wird geladen...

socket send() und recv() dynamisch machen? - Ähnliche Themen

  1. GlassFish Server 4.0 unterstützt Java EE 7 und Websockets

    GlassFish Server 4.0 unterstützt Java EE 7 und Websockets: Oracle hat die Open-Source-Edition des skalierbaren Java-Applikationen-Servers Glassfish in der Version 4.0 fertiggestellt. Glassfish 4...
  2. Icinga 1.9 mit Socket Queue und asynchroner Verarbeitung

    Icinga 1.9 mit Socket Queue und asynchroner Verarbeitung: Der Nagios-Fork Icinga ist in der Version 1.9 erschienen. Mit dieser Veröffentlichung feiert die Icinga-Gemeinde auch das vierte Jubiläum der...
  3. Nginx 1.4.0 mit Websockets und SPDY

    Nginx 1.4.0 mit Websockets und SPDY: Die Entwickler des freien Webservers Nginx haben Version 1.4.0 mit zahlreichen Neuerungen veröffentlicht, wie zum Beispiel die Unterstützung für...
  4. IDS Suricata 1.4 mit Unix-Sockets und IP-Reputation

    IDS Suricata 1.4 mit Unix-Sockets und IP-Reputation: Die Open Information Security Foundation (OISF) hat das netzwerkbasierte Einbruchserkennungssystem (NIDS) Suricata in der Version 1.4...
  5. "send: Cannot determine peer address" nach Timeout mit UDP Server -Perl Socket eval{}

    "send: Cannot determine peer address" nach Timeout mit UDP Server -Perl Socket eval{}: Mahlzeit, ich habe ein kleines Problem und würde mich über eure Mithilfe freuen! Folgender UDP-Server soll nach einem Timeout über eval{}...