Hallo ICH BRAUCHE Dringend Hilfe. Ich hab folgende Programm Server:
C
- #include <alloca.h>
- #include <assert.h>
- #include <string.h>
- #include <stdio.h>
- #include <unistd.h>
- #include <arpa/inet.h>
- #include "hl_common.h"
- int main(int argc, char** argv) {
- // Turn off output buffering so that we see all messages immediately
- if (setvbuf(stdout, NULL, _IONBF, 0) != 0) {
- perror("setvbuf failed!");
- return 1;
- }
- int sock = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP); // 6 für IPv6 hinzufügen
- if (sock == -1) {
- perror("Cannot create socket");
- return 1;
- }
- struct sockaddr_in6 sa; // 6 für IPv6 hinzufügen
- memset(&sa, 0, sizeof sa);
- sa.sin6_family = AF_INET6;// 6 für IPv6 hinzufügen
- sa.sin6_addr = in6addr_any;// 6 für IPv6 hinzufügen
- sa.sin6_port = htons(PORT);// 6 für IPv6 hinzufügen
- if (bind(sock, (struct sockaddr *) &sa, sizeof sa) == -1) {
- perror("bind failed!");
- close(sock);
- return 1;
- }
- for (;;) {
- struct sockaddr_in6 peer;// 6 für IPv6 hinzufügen
- socklen_t peer_len = sizeof peer;
- char incoming[1+MAXSIZE];
- ssize_t len = recvfrom(sock, incoming, sizeof incoming, 0, (struct sockaddr *) &peer, &peer_len);
- if (len == -1) {
- perror("recvfrom failed");
- break;
- }
- char peeraddr[sizeof peer];// 6 für IPv6 hinzufügen und inet_ntoa
- inet_ntop(AF_INET6, &peer.sin6_addr, peeraddr, sizeof(peeraddr)); //durch inet_ntop erstezen (durch parameterzugabe wird auf char von Zeile 43 zugegriffen)
- assert(strlen(peeraddr) < MAXSIZE);
- if (len <= 1) {
- printf("Message from %s too short\n", peeraddr);
- continue;
- }
- if (incoming[0] != 'M') {
- printf("Weird first byte in message from %s: %i\n", peeraddr, (int) incoming[0]);
- continue;
- }
- incoming[len-1] = '\0'; // Ensure that input is a valid C string
- // Craft message contents
- char* peername = incoming+1;
- const char* hostname = get_hostname();
- char msg[1+17+3*(MAXSIZE-1)+1];
- size_t msglen = snprintf(msg, sizeof msg, "RHello %s (%s)! I am %s.", peername, peeraddr, hostname);
- printf("Sending \"%s\" to %s\n", msg, peeraddr);
- // Send response message
- if (sendto(sock, msg, msglen+1, 0, (struct sockaddr*) &peer, peer_len) == -1) {
- perror("Send failed");
- break;
- }
- }
- // An error occured
- close(sock);
- return 2;
- }
Client:
C
- #include <errno.h>
- #include <netdb.h>
- #include <string.h>
- #include <stdio.h>
- #include <unistd.h>
- #include <arpa/inet.h>
- #include <netinet/in.h>
- #include <sys/socket.h>
- #include <sys/time.h>
- #include <sys/types.h>
- #include "hl_common.h"
- void contact(char* host) {
- // ermitteln der adresse
- struct addrinfo tip, *ergebnis;
- memset(&tip, 0, sizeof tip);
- memset(&ergebnis, 0, sizeof *ergebnis);
- tip.ai_family = AF_UNSPEC; // erlauben von IPv4 oder IPv6
- tip.ai_socktype = SOCK_DGRAM; // Datagram socket
- tip.ai_flags = 0; // Flags
- tip.ai_protocol = 0; // Jedes Protokol
- const char *service = "2673";
- if (getaddrinfo(host, service, &tip, &ergebnis) != 0) { //von vorheriger aufgabe getaddrinfo
- printf("getaddrinfo failed\n");
- return;
- }
- // Create socket
- int sock = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);// 6 für IPv6 hinzufügen
- if (sock == -1) {
- perror("socket creation failed");
- return;
- }
- // Compose message
- char sendbuf[1+MAXSIZE];
- int msglen = snprintf(sendbuf, sizeof sendbuf, "M%s", get_hostname()) + 1;
- // Configure socket timeouts
- struct timeval timeout;
- memset(&timeout, 0, sizeof timeout);
- timeout.tv_sec = 1;
- if (setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof timeout) == -1) {
- perror("setsockopt(SO_RCVTIMEO) failed");
- close(sock);
- return;
- }
- if (setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof timeout) == -1) {
- perror("setsockopt(SO_SNDTIMEO) failed");
- close(sock);
- return;
- }
- // Send message
- if (sendto(sock, sendbuf, msglen, 0, ergebnis->ai_addr, ergebnis->ai_addrlen) == -1) {
- perror("sendto failed");
- close(sock);
- return;
- }
- char recvbuf[4*MAXSIZE];
- struct sockaddr_in6 peer; // 6 für IPv6 hinzufügen
- socklen_t peer_len = sizeof peer;
- size_t msgsize = recvfrom(sock, &recvbuf, sizeof recvbuf, 0, (struct sockaddr*) &peer, &peer_len);
- if (msgsize == -1) {
- if (errno == EWOULDBLOCK) {
- fprintf(stderr, "No response from %s!\n", host);
- close(sock);
- return;
- }
- perror("recvfrom failed");
- close(sock);
- return;
- }
- recvbuf[msgsize-1] = '\0';
- char peeraddr[INET6_ADDRSTRLEN]; // 6 für IPv6 hinzufügen und
- inet_ntop(AF_INET6, &peer,peeraddr, INET6_ADDRSTRLEN); //inet_ntoa durch inet_ntop
- if (recvbuf[0] != 'R') {
- fprintf(stderr, "Reply from %s(%s) does not follow protocol!\n"
- "Expected message type 'R', but got %c\n",
- peeraddr, host, recvbuf[0]);
- close(sock);
- return;
- }
- printf("\"%s\" from %s (%s)\n", recvbuf+1, peeraddr, host);
- close(sock);
- }
- int main(int argc, char** argv) {
- if (argc == 1) {
- fprintf(stderr, "No remote host given!\n");
- printf("Usage: %s server-ip [server-ip..]\n", argv[0]);
- return 1;
- }
- char** host = argv+1;
- while (argc > 1) {
- contact(*host);
- host++;
- argc--;
- }
- return 0;
- }
Jetzt zeigt er aber das falsche bei der ausgabe an.
Ausgabe:
> > > $ ./hl_client ::1 127.0.0.1
> > > "Hello t4 :1)! I am t4." from a00:a71:: :1)
> > > "Hello t4 :ffff:127.0.0.1)! I am t4." from a00:a71:: (127.0.0.1)
Statt a00:a71:: soll da was anderes stehen.
Folgendes habe ich als Erklärung bekommen, kann es jedoch nicht umsetzten.
> > > Das ist etwas fies, weil inet_ntop keine Typüberprüfung für das zweite
> > > Argument vornimmt. Da muss ein Pointer auf ein struct in6_addr
> > > reingegeben
> > > werden.
Kann mir jemand sagen welche Zeile ich wie ändern muss?
Ich bedanke mich schon mal!
Grüße Eraseus