简体   繁体   中英

C/C++ Sockets: IPv6 TCP connection fails if I do anything before it

I have been working on converting a small Windows C++ IPv4 program to be IPv6 compatible and have been banging my head against me desk for while. Something is making any IPv6 function fail.

I've written a simple server/client program that the replicates bug. If I do anything before the call to the client/server function the socket functions fail.

The server will get a WSA 10049 error on the bind function and the client will get a WSA 10049 error on the connect function.

But if the code is commented out it will succeed.

What on earth is going on? I feel like I must be just missing something really simple.

I'm using g++ to compile with the latest version of MINGW.

EDIT: It works always if I change this code back to using IPv4/AF_INET

server.cpp

#include <w32api.h>
#define WINVER                  WindowsVista
#define _WIN32_WINDOWS          WindowsVista
#define _WIN32_WINNT            WindowsVista

#include <winsock2.h>
#include <ws2tcpip.h>

int setupWinSock(){
    WSADATA wsa;

    if (WSAStartup(MAKEWORD(2,2),&wsa) != 0){
        return 1;
    }

    return 0;  
}

void simpleServer(int port){
    printf("SERVER START\n");
    int s, c;
    int reuseaddr = 1;
    struct sockaddr_in6 addr;
    int pid;

    s = socket(AF_INET6, SOCK_STREAM, 0);
    if (s == SOCKET_ERROR){
        printf("socket ERROR IPV6: %d\n", WSAGetLastError());
        return;
   }

   int optval = 1;
   setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (const char*)&optval, sizeof optval);

    addr.sin6_family = AF_INET6;
    addr.sin6_port = htons(port);
    addr.sin6_addr = in6addr_any;

    if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0){
        printf("bind ERROR IPV6: %d\n", WSAGetLastError());
        return;
    }

    if (listen(s, 5) < 0){
        printf("listen ERROR IPV6: %d\n", WSAGetLastError());
        return;
    }


    c = accept(s, NULL, NULL);
    if (c == SOCKET_ERROR) printf("ACCEPT ERROR IPV6: %d\n", WSAGetLastError());
    else                   printf("It works!\n");
    closesocket(s);
    closesocket(c);
}

int main(){
    if (setupWinSock()){
        abort();
    }
    // ANYTHING HERE makes socket functions fail
    // Could be this 
    //double tmp = 100000;
    // tmp = tmp * tmp;
    // This to....
    //std::this_thread::sleep_for(std::chrono::milliseconds(2000));
    simpleServer(8080);
    WSACleanup();
}

client.cpp

#include <w32api.h>
#define WINVER                  WindowsVista
#define _WIN32_WINDOWS          WindowsVista
#define _WIN32_WINNT            WindowsVista

#include <winsock2.h>
#include <ws2tcpip.h>

int setupWinSock(){
    WSADATA wsa;

    if (WSAStartup(MAKEWORD(2,2),&wsa) != 0){
        return 1;
    }

    return 0;  
}


void simpleClient(int port){
    printf("CLIENT START\n");
    int s, x;
    struct sockaddr_in6 addr;

    s = socket(AF_INET6, SOCK_STREAM, 0);
     if (s == SOCKET_ERROR){
         printf("socket ERROR IPV6: %d\n", WSAGetLastError());
         return;
    }

    addr.sin6_family = AF_INET6;
    addr.sin6_port = htons(port);
    inet_pton(AF_INET6, "::1", &addr.sin6_addr);
    x = connect(s, (struct sockaddr *)&addr, sizeof(addr));
    if (x == SOCKET_ERROR) printf("CONNECT ERROR IPV6: %d\n", WSAGetLastError());
    else                   printf("It works!\n");
    closesocket(s);
}

int main(){
    if (setupWinSock()){
        abort();
    }
    // ANYTHING HERE makes socket functions fail
    // Could be this 
    //double tmp = 100000;
    // tmp = tmp * tmp;
    // This to....
    //std::this_thread::sleep_for(std::chrono::milliseconds(2000));
    simpleClient(8080);
    WSACleanup();
}

I think you should zero out addr prior to setting its fields. memset(&addr, 0, sizeof(addr)); Note that you are not initializing some of sockaddr_in6 fields , such as sin6_flowinfo or sin6_scope_id . Probably with extra actions prior to calling server/client functions stack gets polluted and fields left uninitialized are left with "more garbage" values than without those extra actions.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM