how can i bind socket to ipv6 address?

半世苍凉 提交于 2020-01-13 14:05:16

问题


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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!