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.