socket: server-client



  • geht es denn jetzt?

    zu dem code style:

    du includierst alles moegliche, egal ob dus brauchst oder nicht, defs von prototypes sind sehr unschoen platziert, deine schleife(n) sind komisch aufgebaut, du defenierst und initialisiert sachen die du anscheinend net brauchst (oder hab ich was uebersehen oder wieso machst du server_addr und local_addr)...



  • daq schrieb:

    geht es denn jetzt?

    ja, deine version geht - danke!
    find aber den fehler in meiner nicht...

    du includierst alles moegliche, egal ob dus brauchst oder nicht

    naja, socket braucht einiges... ausserdem hab ich länger herumprobiert. aber das ist sicher kein grund den code chaotisch und unübersichtlich zu nennen oder?

    defs von prototypes sind sehr unschoen platziert

    dh: weil nicht in einer header datei? -> kommt noch

    deine schleife(n) sind komisch aufgebaut

    das heißt???

    du defenierst und initialisiert sachen die du anscheinend net brauchst

    jo, hätt vor dem post ein code clean up machen müssen...

    thx für deinen beitrag!!

    cheers



  • hab mal eben eine version geschrieben die dasselbe macht aber in einem etwas sauberen code style, jetzt nur als anregung

    1. einfachere schleifen, bedingungen werden direkt reingebaut
    2. weniger files included (na soviel brauchen sockets jetz auch net ;))
    3. fehlermeldungen werden mit perror zurueckgegeben

    und den rest siehste ja, signal und dns aufloesung is jetz nich drinn, sollte jetz nur mal so als anregung sein, kannst ja nochmal mit deiner version vergleichen, evtl siehste was ich mit "chaotisch und unuebersichtlich" meinte 😉

    server.c

    #include <stdio.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    
    #include "header.h"
    
    int main()
    {
    
            // Definitions
            int sockfd, ret;
            struct sockaddr_in conn_addr;
            char buffer[MSG_LEN];
    
            // Build Socket
            sockfd = socket(AF_INET, SOCK_STREAM, 0);
    
            conn_addr.sin_family      = AF_INET;
            conn_addr.sin_addr.s_addr = htonl(INADDR_ANY);
            conn_addr.sin_port        = SERVER_PORT; 
    
            if ( bind(sockfd, SA &conn_addr, sizeof(conn_addr)) == -1 ) {
                    printf("cannot bind port\n");
                    return 1;
            } 
    
            if ( listen(sockfd, 3) == -1 ) {
                    perror("listen error");
                    return 1;
            } 
    
            // wait for client
            if ( (sockfd = accept(sockfd, NULL, NULL)) == -1 ) {
                perror("accept error");
                return 1;
            } 
    
            // loop to receive data from client and print it out
            while( (ret = recv(sockfd, buffer, MSG_LEN, 0)) > 0) {
                    printf("%s\n", buffer);
                    bzero(&buffer, sizeof(buffer));
            }
    
            if(ret == -1) {
                    perror("recv error");
                    return 1;
            }
    
            return 0;
    }
    

    client.c

    #include <stdio.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    
    #include "header.h"
    
    // array of pointers in which messages are stored
    char *messages[] = {
            "hello server?",
            "are you there",
            "hope so",
            "lalllaaa",
            "fifth",
            "sixth",
            "seventh",
            "eight",
            "nineth",
            "tenth"
    }; 
    
    int main() 
    {
            int sockfd, ret, c;
            char buffer[MSG_LEN];
            struct sockaddr_in conn_addr;
    
            conn_addr.sin_family = AF_INET;
            conn_addr.sin_port = SERVER_PORT;
            inet_pton(AF_INET, SERV_IP , &conn_addr.sin_addr);
    
            sockfd = socket(AF_INET, SOCK_STREAM, 0);
    
            if( (ret = connect(sockfd, SA &conn_addr, sizeof(conn_addr))) < 0) {
                    perror("connect error");
                    return 1;
            }
    
            for(c = 0; c <= NUMBER_OF_MESSAGES; c++) {
                if( (ret = send(sockfd, messages[c], MSG_LEN, 0)) < 0)
                            perror("send error");
                printf("SEND\t%s\n", messages[c]);
            }
    
            close(sockfd);
    
            return 0;
    }
    

    dein hauptfehler, weshalb das garnet erst gehen konnte, lag in deine server schleife

    while ( 1 ) {
    if ( (cli_sd = accept(sd, NULL, NULL)) == -1 ) {
    printf("cannot accept client...\n");
    return FALSE;
    }
    received_bytes = recv(cli_sd, message_buffer, MAXBUFFER, 0);
    if ( received_bytes == FALSE ) {
    printf("error when reading the socket of [%d]\n", cli_sd);
    exit(FALSE);
    } else if ( received_bytes == 0 ) {
    ; /* pending */
    } else {
    printf("received [%s]\n", message_buffer);
    }
    close(cli_sd);
    }

    du nimmst in der schleife die erste connection an, empfaengst den string, gibts ihn aus, SCHLIESST die connection wieder und wartest bei accept. ist ja klar das nur der erste string empfangen wird 😉



  • ups die header fehlte, die is ganz unspektakulaer

    header.h

    #define MSG_LEN 128
    
    #define SERVER_PORT 1337
    
    #define SA (struct sockaddr *)
    
    #define SERV_IP "127.0.0.1"
    
    #define NUMBER_OF_MESSAGES 9
    


  • hey daq!

    cool, danke dir!
    das mit dem SA makro is auch a coole idee 🙂
    stimmt, dein code ist wesentlich übersichtlicher!

    ciao



  • btw. bzero is in der strings.h definiert 🙂
    weiters braucht man für close die unistd.h und für inet_pton die arp/inet.h

    weiters sind "//" keine gültigen kommentare lt. ansi

    :xmas2:

    bei den for/ifs mach ich zB folgendes:
    if_(_bedingung_)
    {
    oder
    for_(_i=0;_bedingung;_i++_)
    {

    dh: leerzeichen sind drinnen. um es lesbarer zu machen und um zu verdeutlichen, dass for/if keine funktionen sind... was hältst du davon?
    danke nochmal!!



  • wieso wird dadurch deutlich das es keine funktionen sind? whitespaces sind C egal, ein funktion call kann genauso aussehen, sagen wir du hast ne funktion geschrieben die bla heisst

    bla ( bla, blubb, bli ) ;

    geht genauso.

    also ich finde das nicht so schoen, das erinnert irgenwie ans plenken

    aber letzendlich muss eh jeder seinen coding style finden 😉



  • ja, das mit funktion_(_sadfd_) is mir klar. aber ich schreib halt bei funktionen KEINE leerzeichen und bei if/while/for schon...

    ciao



  • @daq + hephaistos
    Eine kleine Sache ist noch anzumerken. Überlegt euch mal noch Fehlercodes. Immer nur 1 zurückzugeben ist nicht sehr informativ. Der Benutzer kann mit den Fehlermeldungen natürlich was anfangen, aber was ist, wenn der Aufrufer kein Mensch ist sondern ein anderes Programm? Woran erkennt es nun, was genau schief gelaufen ist?



  • @AJ: hast natürlich recht. für diesen kleinen socket test war das aber nicht von nöten.

    danke trotzdem für den einwand!

    cheers


Anmelden zum Antworten