IPv6 Spike Issue

It seems that the stream does not go in the for loop containing accept in ipv6server.c and therefore cannot accept and connect to the client. What mistake? This code works fine for IPV4, but after changing IPV6 this problem occurs

ipv6server.c

    #include <stdio.h>
    #include <stdlib.h> /* needed for os x */
    #include <string.h> /* for memset */
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <sys/errno.h>   /* defines ERESTART, EINTR */
    #include <sys/wait.h>    /* defines WNOHANG, for wait() */

    #include "port.h"       /* defines default port */

    #ifndef ERESTART
    #define ERESTART EINTR
    #endif

extern int errno;

    void serve(int port);   /* main server function */
    void disconn(void);

    main(int argc, char **argv)
    {
        extern char *optarg;
        extern int optind;
        int c, err = 0; 
        int port = SERVICE_PORT;
        static char usage[] = "usage: %s [-d] [-p port]\n";

    while ((c = getopt(argc, argv, "dp:")) != -1)
        switch (c) {
        case 'p':
            port = atoi(optarg);
            if (port < 1024 || port > 65535) {
                fprintf(stderr, "invalid port number: %s\n", optarg);
                err = 1;
            }
            break;
        case '?':
            err = 1;
            break;
        }
    if (err || (optind < argc)) {
        fprintf(stderr, usage, argv[0]);
        exit(1);
    }
    serve(port);
}

/* serve: set up the service */

    void
    serve(int port)
    {
        int svc;        /* listening socket providing service */
        int rqst;       /* socket accepting the request */
        socklen_t alen;       /* length of address structure */
        struct sockaddr_in6 my_addr;    /* address of this service */
        struct sockaddr_in6 client_addr;  /* client address */
        int sockoptval = 1;
        char hostname[128]; /* host name, for debugging */

    gethostname(hostname, 128);

    /* get a tcp/ip socket */
    /*   AF_INET is the Internet address (protocol) family  */
    /*   with SOCK_STREAM we ask for a sequenced, reliable, two-way */
    /*   conenction based on byte streams.  With IP, this means that */
    /*   TCP will be used */

    if ((svc = socket(AF_INET6, SOCK_STREAM, 0)) < 0) {
        perror("cannot create socket");
        exit(1);
    }

    /* we use setsockopt to set SO_REUSEADDR. This allows us */
    /* to reuse the port immediately as soon as the service exits. */
    /* Some operating systems will not allow immediate reuse */
    /* on the chance that some packets may still be en route */
    /* to the port. */

    setsockopt(svc, SOL_SOCKET, SO_REUSEADDR, &sockoptval, sizeof(int));

    /* set up our address */
    /* htons converts a short integer into the network representation */
    /* htonl converts a long integer into the network representation */
    /* INADDR_ANY is the special IP address 0.0.0.0 which binds the */
    /* transport endpoint to all IP addresses on the machine. */

    memset((char*)&my_addr, 0, sizeof(my_addr));  /* 0 out the structure */
    my_addr.sin6_family = AF_INET6;   /* address family */
    my_addr.sin6_port = htons(port);
    my_addr.sin6_addr = in6addr_any;

        client_addr.sin6_family = AF_INET6;   /* address family */
    client_addr.sin6_port = htons(port);
    client_addr.sin6_addr = in6addr_any;

    /* bind to the address to which the service will be offered */
    if (bind(svc, (struct sockaddr *)&my_addr, sizeof(my_addr)) < 0) {
        perror("bind failed");
        exit(1);
    }

    /* set up the socket for listening with a queue length of 5 */
    if (listen(svc, 5) < 0) {
        perror("listen failed");
        exit(1);
    }

    printf("server started on %s, listening on port %d\n", hostname, port);

    /* loop forever - wait for connection requests and perform the service */
    alen = sizeof(client_addr);     /* length of address */

    for (;;) {
        while ((rqst = accept(svc,
                        (struct sockaddr *)&client_addr, &alen)) < 0) {
            /* we may break out of accept if the system call */
            /* was interrupted. In this case, loop back and */
            /* try again */
            if ((errno != ECHILD) && (errno != ERESTART) && (errno != EINTR)) {
                perror("accept failed");
                exit(1);
            }
        }

        printf("received a connection from: %s port %d\n",
            inet_ntoa(client_addr.sin6_addr), ntohs(client_addr.sin6_port));
            shutdown(rqst, 2);    /* close the connection */
    }
}



    ipv6client.c


    /*
        echoc: a demo of TCP/IP sockets connect

        usage:  client [-h serverhost] [-p port]
    */

    #include <stdio.h>
    #include <stdlib.h> /* needed for os x*/
    #include <string.h> /* for strlen */
    #include <netdb.h>      /* for gethostbyname() */
    #include <sys/socket.h>
    #include <netinet/in.h>

    #include "port.h"       /* defines default port */

    int conn(char *host, int port);
    void disconn(void);

    main(int argc, char **argv)
    {
        extern char *optarg;
        extern int optind;
        int c, err = 0; 
        char *prompt = 0;
        int port = SERVICE_PORT;    /* default: whatever is in port.h */
        char *host = "localhost";   /* default: this host */
        static char usage[] = 
                      "usage: %s [-d] [-h serverhost] [-p port]\n";

    while ((c = getopt(argc, argv, "dh:p:")) != -1)
        switch (c) {
        case 'h':  /* hostname */
            host = optarg;
            break;
        case 'p':  /* port number */
            port = atoi(optarg);
            if (port < 1024 || port > 65535) {
                fprintf(stderr, "invalid port number: %s\n", optarg);
                err = 1;
            }
            break;
        case '?':
            err = 1;
            break;
        }
    if (err || (optind < argc)) {   /* error or extra arguments? */
        fprintf(stderr, usage, argv[0]);
        exit(1);
    }

    printf("connecting to %s, port %d\n", host, port);

    if (!conn(host, port))    /* connect */
        exit(1);   /* something went wrong */

    disconn();    /* disconnect */
    return 0;
}

    int fd;  /* fd is the file descriptor for the connected socket */

    /* conn: connect to the service running on host:port */
    /* return 0 on failure, non-zero on success */
    int
    conn(char *host, int port)
    {
        struct hostent *hp; /* host information */
        unsigned int alen;  /* address length when we get the port number */
        struct sockaddr_in6 myaddr; /* our address */
        struct sockaddr_in6 servaddr;   /* server address */
    printf("conn(host=\"%s\", port=\"%d\")\n", host, port);

    /* get a tcp/ip socket */
    /* We do this as we did it for the server */
    /* request the Internet address protocol */
    /* and a reliable 2-way byte stream */

    if ((fd = socket(AF_INET6, SOCK_STREAM, 0)) < 0) {
        perror("cannot create socket");
        return 0;
    }

    /* bind to an arbitrary return address */
    /* because this is the client side, we don't care about the */
    /* address since no application will connect here  --- */
    /* INADDR_ANY is the IP address and 0 is the socket */
    /* htonl converts a long integer (e.g. address) to a network */
    /* representation (agreed-upon byte ordering */

    memset((char *)&myaddr, 0, sizeof(myaddr));
    myaddr.sin6_family = AF_INET6;
    myaddr.sin6_addr = in6addr_any;
    myaddr.sin6_port = htons(0);

    if (bind(fd, (struct sockaddr *)&myaddr, sizeof(myaddr)) < 0) {
        perror("bind failed");
        return 0;
    }

    /* this part is for debugging only - get the port # that the operating */
    /* system allocated for us. */
        alen = sizeof(myaddr);
        if (getsockname(fd, (struct sockaddr *)&myaddr, &alen) < 0) {
                perror("getsockname failed");
                return 0;
        }
    printf("local port number = %d\n", ntohs(myaddr.sin6_port));

    /* fill in the server address and data */
    /* htons() converts a short integer to a network representation */

    memset((char*)&servaddr, 0, sizeof(servaddr));
    servaddr.sin6_family = AF_INET6;
    servaddr.sin6_port = htons(port);

    /* look up the address of the server given its name */
    hp = gethostbyname(host);
    if (!hp) {
        fprintf(stderr, "could not obtain address of %s\n", host);
        return 0;
    }

    /* put the host address into the server address structure */
    memcpy((void *)&servaddr.sin6_addr, hp->h_addr_list[0], hp->h_length);

    /* connect to server */
    if (connect(fd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) {
        perror("connect failed");
        return 0;
    }
    return 1;
}

    /* disconnect from the service */
    void
    disconn(void)
    {
        printf("disconn()\n");
        shutdown(fd, 2);    /* 2 means future sends & receives are disallowed */
    }
+3
source share
2 answers

hp = gethostbyname(host);

How do you know this returns an IPv6 address if you pass it "localhost"? It probably returns an IPv4 address, and everything goes up if you try to copy it toservaddr.sin6_addr

getaddrinfo() AF_INET6 (, , , . ) in6addr_loopback localhost.

+5

:

  • errno - . int
  • ( @Boofhead) bind
  • getaddrinfo() gethostbyname() , . gethostbyname() IPv6

3 - . MacOS X CentOS 5 gethostbyname() IPv4-.

+4

All Articles