问题
I am trying to port ipv4 applications to ipv6 but I can't bind the socket to the ipv6 address.
The problem is here:
err=bind(listening, (sockaddr*)&hint, sizeof(hint));
The err
should be 0 but in this code it returns -1. What is going wrong ?
SOCKET listening = socket(AF_INET6, SOCK_STREAM, 0);
if (listening == INVALID_SOCKET)
{
cerr << "Can't create a socket! Quitting" << endl;
return;
}
int err;
// Bind the ip address and port to a socket
sockaddr_in6 hint;
hint.sin6_family = AF_INET6;
hint.sin6_flowinfo = 0;
hint.sin6_port = htons(54000);
hint.sin6_addr = in6addr_any;
err=bind(listening, (sockaddr*)&hint, sizeof(hint)); //<======= here
回答1:
Rather than populate the sockaddr_in6
manually, you can (and should) use getaddrinfo() instead and let it allocate a properly filled sockaddr_in6
for you, eg:
int err;
SOCKET listening = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);
if (listening == INVALID_SOCKET)
{
err = WSAGetLastError(); // or errno on non-Windows platforms...
cerr << "Can't create a socket! Error " << err << ". Quitting" << endl;
return;
}
// Bind the ip address and port to a socket
addrinfo hint = {};
hint.ai_flags = AI_NUMERICHOST | AI_PASSIVE;
hint.ai_family = AF_INET6;
hint.ai_socktype = SOCK_STREAM;
hint.ai_protocol = IPPROTO_TCP;
addrinfo *res;
err = getaddrinfo("::0", "54000", &hint, &res);
if (err != 0)
{
cerr << "Can't get address to bind the socket! Error " << err << ". Quitting" << endl;
closesocket(listening); // or close() on non-Windows platforms...
return;
}
err = bind(listening, res->ai_addr, res->ai_addrlen);
if (err == SOCKET_ERROR)
{
err = WSAGetLastError(); // or errno on non-Windows platforms...
cerr << "Can't bind the socket! Error " << err << ". Quitting" << endl;
freeaddrinfo(res);
closesocket(listening); // or close() on non-Windows platforms...
return;
}
freeaddrinfo(res);
...
回答2:
This might depend on your platform, but on Linux since 2.4 the sockaddr_in6
structure also contains a sin6_scope_id
member for defining the IPv6 scope, and since the variable hint
is on the stack, it's got random data in it.
The IPv6 scope describes what kind of address it is: unicast, multicast, link local, and a few others, and I have only a drive-by knowledge of them. But if there's garbage in there, it could be a thing.
Recommend ruling this out as an issue by either hard-setting sin6_scope_id
to zero, or (better) just zero out the entire sockaddr_in6
structure before assigning stuff to it; I've long done this with my sockaddr_in
variables just to be sure I didn't end up with junk I didn't want.
memset(&hint, 0, sizeof hint);
And yes, the errno
is really important.
来源:https://stackoverflow.com/questions/58531087/how-can-i-bind-socket-to-ipv6-address