J
JohannesWilde
Guest
Hi there,
I tried to connect a local IPv6 UDP socket to a remote IPv4 IP, as follows:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <iostream>
#include <winsock2.h>
#include <Ws2tcpip.h>
#include <io.h>
int getUdpAddrInfo_(const std::string &ip, const std::string &port, addrinfo **result)
{
struct addrinfo hints;
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_socktype = SOCK_DGRAM; /* Datagram socket */
hints.ai_family = AF_UNSPEC; /* Allow IPv4 and IPv6 */
// For Linux and Windows Vista onwards, further specify options
hints.ai_flags = (AI_V4MAPPED | AI_ALL | AI_ADDRCONFIG); /* For wildcard IP address */
hints.ai_protocol = IPPROTO_UDP; /* UDP protocol */
hints.ai_canonname = NULL;
hints.ai_addr = NULL;
hints.ai_next = NULL;
int const s = getaddrinfo(
/* ip */ ip.data(),
/* port */ port.data(),
/* hints */ &hints,
/* list */ result);
return s;
}
int main( int argc, char *argv[])
{
WORD wVersionRequested = MAKEWORD(2, 2);
WSADATA wsaData;
int const wsaStartupStatus = WSAStartup(wVersionRequested, &wsaData);
std::string const ipLocal("::");
std::string const portLocal("1234");
std::string const ipRemote("127.0.0.1");
std::string const portRemote("2345");
struct addrinfo *result;
int s = getUdpAddrInfo_(ipLocal, portLocal, &result);
if (s != 0)
{
exit(1);
}
SOCKET connectedSocket = INVALID_SOCKET;
if (nullptr == result)
{
exit(1);
}
struct addrinfo *rp = nullptr;
for (rp = result; rp != NULL; rp = rp->ai_next)
{
SOCKET sock = socket(rp->ai_family,
rp->ai_socktype,
rp->ai_protocol);
if (INVALID_SOCKET == sock)
{
continue;
}
else
{
if (AF_INET6 == rp->ai_family)
{
DWORD const ipv6Only = 0; // 0 - false
int const errorCode = setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (char const *)(&ipv6Only), sizeof(ipv6Only));
if (NO_ERROR != errorCode)
{
exit(1);
}
}
if (bind(sock, rp->ai_addr, rp->ai_addrlen) == NO_ERROR)
{
// connect
struct addrinfo *result2;
int const s2 = getUdpAddrInfo_(ipRemote, portRemote, &result2); // (1)
if (s2 != 0)
{
exit(1);
}
struct addrinfo *rp2 = nullptr;
bool connected = false;
if (result2)
{
for (rp2 = result2; rp2 != NULL; rp2 = rp2->ai_next)
{
if (connect(sock, rp2->ai_addr, rp2->ai_addrlen) == NO_ERROR)
{
connected = true;
break;
}
}
}
freeaddrinfo(result2);
if (connected)
{
connectedSocket = sock;
break;
}
}
else
{
closesocket(sock);
}
}
}
freeaddrinfo(result); /* No longer needed */
std::cout << "socket: " << connectedSocket << std::endl;
closesocket(connectedSocket);
WSACleanup();
exit(0);
}
The getUdpAddrInfo_ at (1) however only returns an IPv4 and no IPv6-mapped IPv4 address.
If I instead set
hints.ai_family = AF_INET6;
then the IPv4-mapped IPv6 address is returned as desired. Do I have to explicitely check what kind of socket I want to connect and ask for an appropriate address? Why does it not return the IPv6-mapped IPv4 address?
Best regards,
Johannes
Continue reading...
I tried to connect a local IPv6 UDP socket to a remote IPv4 IP, as follows:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <iostream>
#include <winsock2.h>
#include <Ws2tcpip.h>
#include <io.h>
int getUdpAddrInfo_(const std::string &ip, const std::string &port, addrinfo **result)
{
struct addrinfo hints;
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_socktype = SOCK_DGRAM; /* Datagram socket */
hints.ai_family = AF_UNSPEC; /* Allow IPv4 and IPv6 */
// For Linux and Windows Vista onwards, further specify options
hints.ai_flags = (AI_V4MAPPED | AI_ALL | AI_ADDRCONFIG); /* For wildcard IP address */
hints.ai_protocol = IPPROTO_UDP; /* UDP protocol */
hints.ai_canonname = NULL;
hints.ai_addr = NULL;
hints.ai_next = NULL;
int const s = getaddrinfo(
/* ip */ ip.data(),
/* port */ port.data(),
/* hints */ &hints,
/* list */ result);
return s;
}
int main( int argc, char *argv[])
{
WORD wVersionRequested = MAKEWORD(2, 2);
WSADATA wsaData;
int const wsaStartupStatus = WSAStartup(wVersionRequested, &wsaData);
std::string const ipLocal("::");
std::string const portLocal("1234");
std::string const ipRemote("127.0.0.1");
std::string const portRemote("2345");
struct addrinfo *result;
int s = getUdpAddrInfo_(ipLocal, portLocal, &result);
if (s != 0)
{
exit(1);
}
SOCKET connectedSocket = INVALID_SOCKET;
if (nullptr == result)
{
exit(1);
}
struct addrinfo *rp = nullptr;
for (rp = result; rp != NULL; rp = rp->ai_next)
{
SOCKET sock = socket(rp->ai_family,
rp->ai_socktype,
rp->ai_protocol);
if (INVALID_SOCKET == sock)
{
continue;
}
else
{
if (AF_INET6 == rp->ai_family)
{
DWORD const ipv6Only = 0; // 0 - false
int const errorCode = setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (char const *)(&ipv6Only), sizeof(ipv6Only));
if (NO_ERROR != errorCode)
{
exit(1);
}
}
if (bind(sock, rp->ai_addr, rp->ai_addrlen) == NO_ERROR)
{
// connect
struct addrinfo *result2;
int const s2 = getUdpAddrInfo_(ipRemote, portRemote, &result2); // (1)
if (s2 != 0)
{
exit(1);
}
struct addrinfo *rp2 = nullptr;
bool connected = false;
if (result2)
{
for (rp2 = result2; rp2 != NULL; rp2 = rp2->ai_next)
{
if (connect(sock, rp2->ai_addr, rp2->ai_addrlen) == NO_ERROR)
{
connected = true;
break;
}
}
}
freeaddrinfo(result2);
if (connected)
{
connectedSocket = sock;
break;
}
}
else
{
closesocket(sock);
}
}
}
freeaddrinfo(result); /* No longer needed */
std::cout << "socket: " << connectedSocket << std::endl;
closesocket(connectedSocket);
WSACleanup();
exit(0);
}
The getUdpAddrInfo_ at (1) however only returns an IPv4 and no IPv6-mapped IPv4 address.
If I instead set
hints.ai_family = AF_INET6;
then the IPv4-mapped IPv6 address is returned as desired. Do I have to explicitely check what kind of socket I want to connect and ask for an appropriate address? Why does it not return the IPv6-mapped IPv4 address?
Best regards,
Johannes
Continue reading...