[C] Socket für TCP/UDP Übertragung programmieren

AW: [C] Socket für TCP/UDP Übertragung programmieren

1. Tu dir bitte einen gefallen und fang endlich an Fehlermeldungen und Man-Pages zu lesen! Dich juckt kein bisschen was der Compiler bzw die einzelnen Programme generell ausgeben (siehe deine mount-Versuche - der sagt dir doch klipp und klar wo der Fehler liegt).
2. Solange sowas
Code:
/* close() - Socket freigeben */
    int close(sockfd);
, fehlende Klammern und Zeiger-wo-keine-Zeiger hingehören (allerbestets Beispiel wo es schon fast schmerzt: scanf) im Code sind, wundert es mich im Prinzip erstmal, dass das überhaupt Übersetzt wird (bei mir tut's das nicht). Das es nicht funktioniert, wundert mich hingegen kein Stück weit. Und bevor die Fehler nicht aus dem Code draußen sind, macht es meiner Meinung nach auch keinen Sinn, den Fehler bei Linux oder irgendeiner VM Lösung zu suchen...

Also, drei Dinge die du hoffentlich tust:
1. Fehlermeldungen lesen und interpretieren (die erste Zahl sagt die Zeile, die zweite Zahl gibt das Zeichen an wo der Fehler bemerkt wurde - die Zeile ist OFT hilfreich!).
2. Man Pages und deren Posix Varianten (Linux ist in der Regel nicht vollständig Posix konform, wenn auch zum allergrößten Teil) anschauen. Posix Varianten findest du auch, wenn du nach "opengroup $funktion", also z.b. "opengroup posix" suchst.
3. Bei Speicherfehlern und auch sonst generell und immer und überhaupt: Valgrind verwenden.

Ich (und vermutlich auch andere) wären dir auch dankbar, wenn der Code mit folgenden Optionen kompiliert:
-Wall -Werror -pedantic -std=c99
DANN hast du nämlich schon einen ganzen Haufen "C" Fehler ausgebessert, und wir können uns dem Kern Problem zuwenden...
 
Zuletzt bearbeitet:
AW: [C] Socket für TCP/UDP Übertragung programmieren

wieso machste das eigentlich in ner vm? vllt liegt da ja der hase begraben.
Ich muss mit diesen VMs arbeiten. Siehe Angabe im Starposting. Ich glaube aber eher nicht, dass die Fehler daher kommen. Wenn man googelt, sieht man, dass genug andere Leute, die nicht mit VMs arbeiten, die Fehler auch haben. Ich vermute schon stark, dass es am Code liegt.

Zu deinen anderen Fragen kann ich leider nichts sagen. Ich beschäftige mich zum allerersten Mal mit solchen Sachen.

@ Dragonix
Von welcher Version meines Codes redest du? Schau dir die an, die ich in meinem letzten Posting vor diesem gepostet habe, das ist nämlich die aktuelle. Dabei bekomme ich nur noch 2 errors raus:

udp.JPG tcp.JPG

Bin auch schon die ganze Zeit dabei, diese man durchzuforsten, aber noch konnte ich die beiden Fehler nicht beheben. In den close() Funktionen habe ich jetzt BTW int close(int sockfd); stehen.

Im Code müssen noch 2 od. 3 semantische Fehler drinnen stecken, die keine Datenübertragung über das VM-Netzwerk zulassen. Siehe Fehlermeldungen, die ich im vorigen Posting beschrieben habe ...

[EDIT]
Das wäre jetzt der Code in einem Stück:
Code:
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#ifdef _WIN32
#include <winsock.h>
#else
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
#endif

void [COLOR=purple][B]tcp_server[/B](int port) {
    [COLOR=seagreen]/* socket() - Socket anfordern */    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd == -1) {
        perror("socket()");
    }

    [COLOR=seagreen]/* bind() - Den eigenen Port festlegen */    struct sockaddr_in my_addr;
    my_addr.sin_family = AF_INET;
    my_addr.sin_port = htons(port);
    my_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == -1) {
        perror("bind()");
    }
    [COLOR=seagreen]/* Zugewiesenen Port ermitteln: */    socklen_t len;
    getsockname(sockfd, (struct sockaddr *)&my_addr, &len);
    printf("Port: %d\n", ntohs(my_addr.sin_port));

    [COLOR=seagreen]/* listen() - Auf eingehende Verbindungen warten */    if (listen(sockfd, 5) == -1) {
        perror("listen()");
    }

    [COLOR=seagreen]/* accept() - Die eingehende Verbindung annehmen */     socklen_t sin_size = sizeof(struct sockaddr_in);
    struct sockaddr_in remote_host;
    int sock2 = accept(sockfd, (struct sockaddr *)&remote_host, &sin_size);
    if (sock2 == -1) {
        perror("accept()");
    }

    [COLOR=seagreen]/* recv() - Empfangen mit TCP */    ssize_t msg_length;
    char buf[1024];
    if (msg_length = recv(sock2, buf, 1024, 0) == -1) {
        perror("recv()");
    }
    int i=0;
    printf("message: ");
    while (i<msg_length) {
        printf("%c", buf[i]);
        i++;
    }
    printf("\naccepted connection from [%s:%d]\n", inet_ntoa(remote_host.sin_addr), ntohs(remote_host.sin_port));

    [COLOR=seagreen]/* close() - Socket freigeben */    int close(int sockfd); 
}

void [COLOR=purple][B]tcp_client[/B](char *data, int port, char *server_ip) {
    [COLOR=seagreen]/* socket() - Socket anfordern */    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd == -1) {
        perror("socket()");
    }

    [COLOR=seagreen]/* connect() - Verbindung aufbauen */    struct sockaddr_in serv_addr;
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(port); 
    serv_addr.sin_addr.s_addr = inet_aton(server_ip, &serv_addr.sin_addr);
    if (connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(struct sockaddr)) == -1) {
        perror("connect()");
    }

    [COLOR=seagreen]/* send() - Senden mit TCP */    char *msg = data;
    int len = strlen(msg);
    if (send(sockfd, msg, len, 0) == -1) {
        perror("send()");
    }

    [COLOR=seagreen]/* close() - Socket freigeben */    int close(int sockfd); 
}

void [COLOR=purple][B]udp_server[/B](int port) {
    [COLOR=seagreen]/* socket() - Socket anfordern */    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd == -1) {
        perror("socket()");
    }

    [COLOR=seagreen]/* bind() - Den eigenen Port festlegen */    struct sockaddr_in my_addr;
    my_addr.sin_family = AF_INET;
    my_addr.sin_port = htons(port);
    my_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == -1) {
        perror("bind()");
    }
    [COLOR=seagreen]/* Zugewiesenen Port ermitteln: */    socklen_t len;
    getsockname(sockfd, (struct sockaddr *)&my_addr, &len);
    printf("Port: %d\n", ntohs(my_addr.sin_port));

    [COLOR=seagreen]/* recvfrom() - Empfangen mit UDP */    ssize_t msg_length;
    struct sockaddr_in remote_host;
    char buf[1024];
    if (msg_length = recvfrom(sockfd, buf, 1024, 0, (struct sockaddr *)&remote_host, &len) == -1) {
        perror("recvfrom()");
    }
    int i=0;
    printf("message: ");
    while (i<msg_length) {
        printf("%c", buf[i]);
        i++;
    }
    printf("\naccepted connection from [%s:%d]\n", inet_ntoa(remote_host.sin_addr), ntohs(remote_host.sin_port));

    [COLOR=seagreen]/* close() - Socket freigeben */    int close(int sockfd); 
}

void [COLOR=purple][B]udp_client[/B](char *data, int port, char *server_ip) {
    [COLOR=seagreen]/* socket() - Socket anfordern */    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd == -1) {
        perror("socket()");
    }

    [COLOR=seagreen]/* sendto() - Senden mit UDP */    char *msg = data;
    int len = strlen(msg);
    struct sockaddr_in serv_addr;
    if (sendto(sockfd, msg, len, 0, (struct sockaddr *)&serv_addr, &len) == -1) {
        perror("sendto()");
    }

    [COLOR=seagreen]/* close() - Socket freigeben */    int close(int sockfd); 
}

[COLOR=seagreen]/* Parameter: UDP/TCP, Client, Server-IPv4-Adresse, Port */
/* Parameter: UDP/TCP, Server, Port */int main(int argc, char *argv[]) {
    int port, size1=4096, size2=1024;
    char *data = (char*)malloc(size1 * sizeof(char));
    char *server_ip = (char*)malloc(size2 * sizeof(char));

    if ((strcmp(argv[1], "TCP")==0) && (strcmp(argv[2], "Server")==0)) {
        if (argc!=4) {
            printf("Parameters missing or too many parameters!\n");
            return -1;
        } else {
            port = atoi(argv[3]);
            tcp_server(port);
        }
    } else if ((strcmp(argv[1], "TCP")==0) && (strcmp(argv[2], "Client")==0)) {
        if (argc!=5) {
            printf("Parameters missing or too many parameters!\n");
            return -1;
        } else {
            server_ip = argv[3];
            port = atoi(argv[4]);
            printf("Please enter message: ");
            scanf("%s", data);
            tcp_client(data, port, server_ip);
            free(data);
            free(server_ip);
        }
    } else if ((strcmp(argv[1], "UDP")==0) && (strcmp(argv[2], "Server")==0)) {
        if (argc!=4) {
            printf("Parameters missing or too many parameters!\n");
            return -1;
        } else {
            port = atoi(argv[3]);
            udp_server(port);
        }
    } else if ((strcmp(argv[1], "UDP")==0) && (strcmp(argv[2], "Client")==0)) {
        if (argc!=5) {
            printf("Parameters missing or too many parameters!\n");
            return -1;
        } else {
            server_ip = argv[3];
            port = atoi(argv[4]);
            printf("Please enter message: ");
            scanf("%s", data);
            udp_client(data, port, server_ip);
            free(data);
            free(server_ip);
        }
    }

    return 0;
}
^^ Bei den scanfs hast du doch gemeint, dass das & vor data weg müsste?!

Hier noch einmal die verbliebenen Fehler in einem:

socket.JPG
 
Zuletzt bearbeitet:
AW: [C] Socket für TCP/UDP Übertragung programmieren

das -o muss direkt vor dem Wunschnamen der Ausgabe Binärdatei stehen, also "-o tcpserver".
Les dir in der man page durch, was inet_aton zurückgibt und denk dann mal drüber nach, ob das hier überhaupt passt so wie du das hast (aber das bemängelt er hier nichtmal).
Was er bemängelt (s. manpage):
Code:
 inet_aton() is not specified in POSIX.1-2001, but is available on most
       systems.
Auf deutsch: Nicht wirklich gebräuchlich diese Funktion (das die Übersetzung *sehr* frei ist und durchaus Interpretation enthält, ist mir bewusst ;)). Ich hab die hier auch das erste mal gesehen...
Aber gucken wir mal in den angebenen Header (idr zu finden unter /usr/include/arpa/inet.h). Da steht:
Code:
/* The following functions are not part of XNS 5.2.  */
#ifdef __USE_MISC
/* Convert Internet host address from numbers-and-dots notation in CP
   into binary data and store the result in the structure INP.  */
extern int inet_aton (const char *__cp, struct in_addr *__inp) __THROW;
Dann schauen wir in die /usr/include/features.h (die wird hier nämlich inkludiert und "features" und "functions are not part" passt doch schonmal gut zusammen, und dann auch noch ein #ifdef - verdächtig!) und da steht (bzgl. __USE_MISC, viel zu lesen ich weiß): Definiere z.B. _BSD_SOURCE oder gleich _GNU_SOURCE (also entweder per #define oben in die Datei vor dem entsprechenden #include oder per Anweisung an den Kompilierer -D_GNU_SOURCE).
Da sehen wir ein ifdef, der ganze Abschnitt (also auch unser inet_aton) gibt's also nur geliefert, wenn wir __USE_MISC definieren.

Alternativ: Anders machen (wie gesagt, wüsste nicht, wann ich die Funktion jemals verwendet hätte).

Bei deinem anderen Fehler sollte dir die manpage helfen (er meint wirklich das 6. Argument, zähls ruhig durch und schau auf die Datentypen).

Und was ist mit dem scanf? Das wundert er mich, dass er dir das bei dir nicht anprangert, aber probiers mal mit der richtig sortierten Befehlszeile (dein -o verschluckt das -Wall).

Grüße und viel Erfolg
Matthias

Edit:
Und was
Code:
/* close() - Socket freigeben */
    int close(int sockfd);
soll, hast du mir immernochnicht erklärt. Natürlich durchaus möglich, dass ich's einfach nicht kenne, aber der Sinn davon erschließt sich mir in keinster Weise...
 
Zuletzt bearbeitet:
AW: [C] Socket für TCP/UDP Übertragung programmieren

Code:
gcc -Wall -Werror -pedantic -std=c99 -o socket socket.c
Ok, das bringt mich soweit:
socket.JPG
Code:
#define __USE_MISC
^^ Das scheint jedenfalls nicht viel gebracht zu haben. Ich hätte es ja auch noch so probiert gehabt:
Code:
#if defined _BSD_SOURCE || defined _SVID_SOURCE 
#define __USE_MISC     1 
#endif
 
Zuletzt bearbeitet:
AW: [C] Socket für TCP/UDP Übertragung programmieren

Ich bin mir nicht ganz sicher wie du das meinst:
Wenn du direkt #define __USE_MISC gemacht hast, dann schau mal an den Anfang der features.h

Code:
/* Undefine everything, so we get a clean slate.  */
...
#undef  __USE_MISC
...
(#undef ist klar? Wenn irgendwo vorher ein #define __USE_MISC war, dann wird das hier an dieser Stelle "gelöscht").

Du sollst nicht __USE_MISC direkt verwenden, sondern (das viel Aussagekräftigere) _BSD_SOURCE oder eben _GNU_SOURCE (Zitat features.h "All of the above, plus GNU extensions.", und _BSD_SOURCE steth drüber, also aktiviert _GNU_SOURCE auch _BSD_SOURCE).

Wichtig ist natürlich auch, dass du das schon VOR dem Inkludieren des Headers machst. Alternativ eben wie bereits geschrieben einfach "-D_GNU_SOURCE" (ohne die "") an cc übergeben, siehe dazu auch man gcc, bzw.:
Code:
-D name=definition
           The contents of definition are tokenized and processed as if they
           appeared during translation phase three in a #define directive.
           In particular, the definition will be truncated by embedded
           newline characters.

Und noch ein edit (falls du es jemals liest, ich hab's erst jetzt bemerkt ;)):
^^ Bei den scanfs hast du doch gemeint, dass das & vor data weg müsste?!
Jep.

Noch ein edit: Wenn du's per #define machst, füge das #define am besten in der ersten Zeile ein. Kann sonst durchaus zu unliebsamen Querverbindungen kommen (d.h. kann durchaus auf mehrere #includes haben).

Noch ein edit: Der letzte Fehler geht aber am schnellsten...
 
Zuletzt bearbeitet:
AW: [C] Socket für TCP/UDP Übertragung programmieren

^^ Habe oben noch ein Bisschen rumeditiert. Bitte siehe voriges Posting für aktuellen Stand.

Ich probiere jetzt noch das Makro mit _GNU_SOURCE. Mal schauen, ob inet_aton dann ordentlich erkannt wird ...

[EDIT]
Nein, #define _GNU_SOURCE hat auch nichts gebracht. Die Fehlermeldung mit inet_aton (siehe Screenshot im vorigen Posting) bleibt nach wie vor.

[EDIT2]
Ok, das "vor dem Inkludieren des Headers" habe ich zu spät gelesen. Jetzt, wo das #define _GNU_SOURCE ganz am Anfang über allen Headern steht, funktioniert das mit dem inet_aton scheinbar. ;) Und wir sind beim letzten Fehler angekommen:

socket.JPG

Jetzt erst mal Mittagessen, dann überlege ich mir das mit dem pointer. Schon mal vielen Dank bis hierher! :daumen:
 
Zuletzt bearbeitet:
AW: [C] Socket für TCP/UDP Übertragung programmieren

Wenn ich mir die man für sendto ansehe und die Fehlermeldung im Kopf habe, schließe ich folgendes:

Code:
 ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
                      const struct sockaddr *dest_addr, [B]socklen_t addrlen[/B]);
Der fett markierte Teil muss die Größe der sockaddr-Struktur enthalten, also bspw. sizeof(serv_addr) bei dir. Die Fehlermeldung sagt dir in dem Fall sogar haargenau, was da nicht passt.
 
AW: [C] Socket für TCP/UDP Übertragung programmieren

Wenn ich mir die man für sendto ansehe und die Fehlermeldung im Kopf habe, schließe ich folgendes:

Code:
 ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
                      const struct sockaddr *dest_addr, [B]socklen_t addrlen[/B]);
Der fett markierte Teil muss die Größe der sockaddr-Struktur enthalten, also bspw. sizeof(serv_addr) bei dir. Die Fehlermeldung sagt dir in dem Fall sogar haargenau, was da nicht passt.

Jetzt verrat ihm halt nicht alles, das soll er doch selber lernen :motz: :D

Ich warte übrigens immer noch auf die Erklärung von
Code:
/* close() - Socket freigeben */
    int close(int sockfd);
 
AW: [C] Socket für TCP/UDP Übertragung programmieren

^^ Auf das sizeof wäre ich eh selbst auch schon gekommen (steht das nicht in irgendeinem meiner vorigen Postings?! K.A. ich gehe das jetzt auch nicht suchen, egal ;)) ... das Problem scheinen hier viel mehr die Werte (fett/blau) selbst zu sein. Zumindest das remote_host kommt mir noch leicht Spanisch vor ...
Code:
void udp_server(int port) {
    [COLOR=seagreen]/* socket() - Socket anfordern */    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd == -1) {
        perror("socket()");
    }

    [COLOR=seagreen]/* bind() - Den eigenen Port festlegen */    struct sockaddr_in my_addr;
    my_addr.sin_family = AF_INET;
    my_addr.sin_port = htons(port);
    my_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == -1) {
        perror("bind()");
    }
    [COLOR=seagreen]/* Zugewiesenen Port ermitteln: */    socklen_t len;
    getsockname(sockfd, (struct sockaddr *)&my_addr, &len);
    printf("Port: %d\n", ntohs(my_addr.sin_port));

    [COLOR=seagreen]/* recvfrom() - Empfangen mit UDP */    ssize_t msg_length;
    struct sockaddr_in remote_host;
    char buf[1024];
    if ((msg_length = recvfrom(sockfd, buf, 1024, 0, (struct sockaddr *)&[COLOR=royalblue][B]remote_host[/B], sizeof([COLOR=royalblue][B]remote_host[/B]))) == -1) {
        perror("recvfrom()");
    }
    int i=0;
    printf("message: ");
    while (i<msg_length) {
        printf("%c", buf[i]);
        i++;
    }
    printf("\naccepted connection from [%s:%d]\n", inet_ntoa(remote_host.sin_addr), ntohs(remote_host.sin_port));

    [COLOR=seagreen]/* close() - Socket freigeben */    int close(int sockfd); 
}

void udp_client(char *data, int port, char *server_ip) {
    [COLOR=seagreen]/* socket() - Socket anfordern */    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd == -1) {
        perror("socket()");
    }

    [COLOR=seagreen]/* sendto() - Senden mit UDP */    char *msg = data;
    int len = strlen(msg);
    struct sockaddr_in serv_addr;
    if (sendto(sockfd, msg, len, 0, (struct sockaddr *)&[COLOR=royalblue][B]serv_addr[/B], sizeof([COLOR=royalblue][B]serv_addr[/B])) == -1) {
        perror("sendto()");
    }

    [COLOR=seagreen]/* close() - Socket freigeben */    int close(int sockfd); 
}
Nur durch das sizeof verschwindet das Problem jedenfalls noch nicht:

socket.JPG
 
Zuletzt bearbeitet:
AW: [C] Socket für TCP/UDP Übertragung programmieren

Ja, das inet_aton war mir auch absolut kein Begriff. Jetzt weiß ich auch warum :D Das macht man dann doch gleich lieber selbst bei so nem kleinen Projekt.

Noch was am Rande.

Gewöhn dir doch bitte solche Aktionen ab:

Code:
if (msg_length = recvfrom(sockfd, buf, 1024, 0, (struct sockaddr *)&remote_host, &len)) == -1)
Das ist nicht gerade sehr hilfreich bzgl Lesbarkeit des Codes.

Und zu den ersten beiden Fehlern.
Da steht doch drin, was du falsch machst. Du machst aus einem Pointer einfach nen Integer, ohne einen Typecast zu machen. Das ist doch klar, dass das nicht funktionieren kann :ugly:

Kann es sein, das dir das Konzept von Pointern, und wie man damit umgeht noch nicht wirklich klar geworden? Wenn ja, mach dir an ganz einfachen Beispielen nochmal klar, was beim (de)referenzieren passiert, und was passiert, wenn man einem Pointer einen Wert zuweist, und dann diesen Wert ändert usw.
 
AW: [C] Socket für TCP/UDP Übertragung programmieren

^^ Dass der Typecast fehlt, kann sogar ich aus der Fehlermeldung rauslesen, nur ich sehe den int einfach nicht (remote_host ist doch kein int?!) ...

Das hier ist das struct:

Capture.JPG

Nur auf was soll ich da jetzt casten? Die ersten beiden sind benutzerdefinierte Datentypen, so wie ich das verstehe, und das dritte ist ja ein Verweis auf ein anderes struct. Und was mich gerade besonders wundert: Wieso klappt's mit dem simplen sizeof bei sendto(), aber nicht bei recvfrom()? Da ist ja nichts anders?! :huh:

^^ Ich probiere jetzt noch was mit den 3 Dingen aus dem Screenshost. Mal sehen, ob ich noch auf was drauf komme ...
 
AW: [C] Socket für TCP/UDP Übertragung programmieren

Geschafft!!! ;)

Habe aber ein Bisschen um das Problem herum gebastelt (wahrscheinlich wäre es auch direkt in der einen recvfrom Zeile gegangen):
Code:
void udp_server(int port) {    
   [COLOR=seagreen] /* socket() - Socket anfordern */    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd == -1) {
        perror("socket()");
    }

    [COLOR=seagreen]/* bind() - Den eigenen Port festlegen */    struct sockaddr_in my_addr;
    my_addr.sin_family = AF_INET;
    my_addr.sin_port = htons(port);
    my_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == -1) {
        perror("bind()");
    }
    [COLOR=seagreen]/* Zugewiesenen Port ermitteln: */    socklen_t len;
    getsockname(sockfd, (struct sockaddr *)&my_addr, &len);
    printf("Port: %d\n", ntohs(my_addr.sin_port));

    [COLOR=seagreen]/* recvfrom() - Empfangen mit UDP */    ssize_t msg_length;
    struct sockaddr_in remote_host;
    [COLOR=royalblue][B]socklen_t clientlen;
    clientlen = sizeof(remote_host);[/B]    char buf[1024];
    if ((msg_length = recvfrom(sockfd, buf, 1024, 0, (struct sockaddr *)&remote_host, [COLOR=royalblue][B]&clientlen[/B])) == -1) {
        perror("recvfrom()");
    }
    int i=0;
    printf("message: ");
    while (i<msg_length) {
        printf("%c", buf[i]);
        i++;
    }
    printf("\naccepted connection from [%s:%d]\n", inet_ntoa(remote_host.sin_addr), ntohs(remote_host.sin_port));

    [COLOR=seagreen]/* close() - Socket freigeben */    int close(int sockfd); 
}
Jetzt sind auf jeden Fall mal sämtliche syntaktischen Fehler beseitigt. Das C File kann ohne errors und warnings compiliert werden:

Capture.JPG

Jetzt muss sich zeigen, ob das Ganze netzwerktechnisch funktioniert. Ich melde mich dann noch einmal ... :)

[EDIT]
Ok, jetzt kommen die Netzwerkfehler. Bei TCP scheitert der Client an connect():

Capture.JPG

^^ Oberer Fensterausschnitt = Client. Unterer = Server. Die Client- und die Server-VM können sich problemlos pingen, also muss es sich hier um einen Code-Fehler in tcp_client bei connect() handeln ...
Code:
void tcp_client(char *data, int port, char *server_ip) {
    [COLOR=seagreen]/* socket() - Socket anfordern */    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd == -1) {
        perror("socket()");
    }

    [COLOR=seagreen]/* connect() - Verbindung aufbauen */    struct sockaddr_in serv_addr;
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(port); 
    serv_addr.sin_addr.s_addr = inet_aton(server_ip, &serv_addr.sin_addr);
    if ([COLOR=royalblue][B]connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(struct sockaddr))[/B] == -1) {
        perror("connect()");
    }

    [COLOR=seagreen]/* send() - Senden mit TCP */    char *msg = data;
    int len = strlen(msg);
    if (send(sockfd, msg, len, 0) == -1) {
        perror("send()");
    }

    [COLOR=seagreen]/* close() - Socket freigeben */    int close(int sockfd); 
}
 
Zuletzt bearbeitet:
AW: [C] Socket für TCP/UDP Übertragung programmieren

Les dir in der man page durch, was inet_aton zurückgibt und denk dann mal drüber nach, ob das hier überhaupt passt so wie du das hast (aber das bemängelt er hier nichtmal).


man page schrieb:
int inet_aton(const char *cp, struct in_addr *inp);
[...]
inet_aton() converts the Internet host address cp from the IPv4 num‐
bers-and-dots notation into binary form (in network byte order) and
stores it in the structure that inp points to
. inet_aton() returns
nonzero if the address is valid, zero if not
.
(Sämtliche Hervorhebungen von mir eingefügt).

serv_addr.sin_addr.s_addr = inet_aton(server_ip, &serv_addr.sin_addr); << d.h. wenn das funktionieren würde wäre es Dus(s)el, aber in keinster weise vom Standard garantiert.

Edit: Um sämtliche Kommunikationsprobleme zwischen den VMs ausschließen zu können, würde ich dir - wie dir bereits schon mehrfach nahegelegt wurde - auch empfehlen, das ganze erstmal in einer VM zu testen...
 
AW: [C] Socket für TCP/UDP Übertragung programmieren

^^ Wie soll ich das Ganze in einer einzigen VM testen? Ich muss ja zuerst den Server starten und solange der dann darauf wartet, dass was passiert, kann ich ja keinen weiteren Befehl eingeben (und damit nicht auch den Client starten) ... ?!

Ich überlege mir jetzt Mal, was du mit dem Code-bezogenen Satz meinen könntest ...
 
AW: [C] Socket für TCP/UDP Übertragung programmieren

^^ Wie soll ich das Ganze in einer einzigen VM testen? Ich muss ja zuerst den Server starten und solange der dann darauf wartet, dass was passiert, kann ich ja keinen weiteren Befehl eingeben (und damit nicht auch den Client starten) ... ?!

Ich überlege mir jetzt Mal, was du mit dem Code-bezogenen Satz meinen könntest ...

Du hast mehrere virtuelle Terminals (Alt + F1, Alt + F2, ...), du könntest einen Befehl gleich in den Hintergrund schieben ("programm &", dann den angegebenen Pid wieder abschießen). Siehe dazu auch z.B. http://de.linwiki.org/wiki/Linuxfibel_-_Erste_Schritte_-_Virtuelle_Konsole .

Dann denk mal drüber nach ;). Tip: Du weißt deiner Adresse *irgendeinen* Wert zu, der von deiner inet_aton zurückkommt.. obwohl inet_aton doch gerade einen korrekten Wert über den Pointer reingeschrieben hat... hm... denk mal nach ;)
 
AW: [C] Socket für TCP/UDP Übertragung programmieren

Du kannst mit screen mehrere "Sessions" gleichzeitig verwenden und zwischen diesen umherschalten (man screen gibt Infos)
 
AW: [C] Socket für TCP/UDP Übertragung programmieren

@ me --> :klatsch:
Natürlich nur:
Code:
inet_aton(server_ip, &serv_addr.sin_addr);
;)

Damit kommt die TCP Kommunikation schon einen Schritt weiter. Immerhin das erste Wort des von mir eingegebenen Teststrings wird schon erfolgreich übertragen und am Server wird auch die IP des Clients erkannt, wo's herkommt ...

Capture.JPG

^^ Damit erübrigt sich zumindest die Frage, ob die Kommunikation zwischen den VMs grundsätzlich funktioniert. Trotzdem danke für die Tipps diesbezüglich!

Allerdings darf ich mir schon wieder überlegen, wo das "Segmentation fault" herkommt ... :ugly:
Ich habe ja doch nicht eine zu kleine Größe für das char Feld data gewählt?!
 
AW: [C] Socket für TCP/UDP Übertragung programmieren

Lass dir mal den vom Client eingelesenen String ausgeben, du wirst merken, dass auch hier schon nach (bzw. vor) dem Leerzeichen schluss ist.

Nehm alternativ z.b. fgets (mit stream auf stdin gesetzt, achtung, liest auch das newline mit, aber das merkste schon); ist eh sicherer als scanf, da du hier die Puffergröße angibst...

Bezüglich dem Segfault: Kann sein, dass das irgendwo daher kommt, aber ich hab mittlerweile den Überblick über die Code Änderungen doch etwas verloren ;). Ansonsten sei nochmal ausdrücklichst auf valgrind verwiesen (valgrind nimmt dir aber nicht die Pflicht, ordentlichen Code zu schreiben - valgrind ist blos ein äußerst praktisches Progrämmchen...)
 
AW: [C] Socket für TCP/UDP Übertragung programmieren

Es gibt auch die Möglichkeit ein Programm mit "&" im Hintergrund zu starten :ugly:

Also Linux bietet da SEHR viele Möglichkeiten :ugly:
 
AW: [C] Socket für TCP/UDP Übertragung programmieren

@ Dragonix
Mit gets funktioniert die komplette TCP-Übertragung, allerdings wird gets vom Linux gcc Compiler offenbar als unsicher erachtet. Ich werde deswegen noch probieren, das Einlesen auf fgets umzuschreiben:

Capture.JPG

^^ Das "Segmentation fault" scheint allerdings nicht am scanf gelegen zu haben, wenn's auch mit anderen Einlese-Funktionen auftaucht. Ich frage mich nur gerade, ob ich's nicht einfach ignorieren kann?! Der zweite Teil der Aufgabenstellung sieht vor, dass ich mit tcpdump die Übertragung aufzeichne und das müsste ja jetzt möglich sein, wo der vollständige Text übertragen wird?! Klar, professionellerweise würde man da jetzt mit valgrind den Code durchchecken, aber ich glaube, wenn ich damit anfange, werde ich mit der Aufgabe bis zur Abgabefrist nicht mehr fertig. Ich wüsste offengestanden nicht einmal, wie ich dieses valgrind Zeugs überhaupt starten müsste, habe mich aber auch noch nicht wirklich eingelesen.

Wie gesagt: Ich probiere jetzt noch fgets und wenn das dann soweit klappt, schauen wir, ob mein UDP-Code funktioniert. Wenn ich bei TCP und UDP eine funktionierende Übertragung habe, dann bin ich gerne bereit, mir das "Segmentation fault" noch einmal anzuschauen. ;)
 
Zurück