创建IPv6套接字失败,IP无效-似乎被截断 我目前正在学习C++,我正在开发一个允许在Windows和Linux上创建套接字的库,支持IPv4和IPv6。p>
我在IPv4上工作得很好,但我在IPv6上遇到了问题 我尝试过这样做,它绑定到一个IP地址或绑定到一个特定的IPV6地址,但要么失败 下面是我如何创建套接字的创建IPv6套接字失败,IP无效-似乎被截断 我目前正在学习C++,我正在开发一个允许在Windows和Linux上创建套接字的库,支持IPv4和IPv6。p>,c++,sockets,C++,Sockets,我在IPv4上工作得很好,但我在IPv6上遇到了问题 我尝试过这样做,它绑定到一个IP地址或绑定到一个特定的IPV6地址,但要么失败 下面是我如何创建套接字的 this->serverSocket = socket(family, socketType, 0); if (this->serverSocket < 0) { stringstream logstream; logstream <&
this->serverSocket = socket(family, socketType, 0);
if (this->serverSocket < 0)
{
stringstream logstream;
logstream << "Error opening socket. Most likely trying to bind to an ";
logstream << "invalid IP or the port is already in use";
bitsLibrary->writeToLog(logstream.str(), "LinuxSocket", "createSocket");
return false;
}
switch (family)
{
case AF_INET: {
this->serv_addr = new sockaddr();
bzero((sockaddr*)this->serv_addr, sizeof(this->serv_addr));
sockaddr_in *sin = reinterpret_cast<sockaddr_in*>(serv_addr);
sin->sin_family = family;
//sin->sin_addr.s_addr = INADDR_ANY;
//If IP Address is NULL then set to IPADDR_ANY
if (ipAddress.empty())
{
sin->sin_addr.s_addr = INADDR_ANY;
}
else
{
inet_pton(AF_INET, ipAddress.c_str(), &sin->sin_addr);
}
sin->sin_port = htons(port);
break;
}
case AF_INET6: {
this->serv_addr = new sockaddr();
bzero((sockaddr*)this->serv_addr, sizeof(this->serv_addr));
sockaddr_in6 *sin = reinterpret_cast<sockaddr_in6*>(serv_addr);
sin->sin6_family = family;
if (ipAddress.empty())
{
sin->sin6_addr = IN6ADDR_ANY_INIT;
}
else
{
inet_pton(AF_INET6, ipAddress.c_str(), &(sin->sin6_addr));
}
sin->sin6_port = htons(port);
break;
}
default:
this->bitsLibrary->writeToLog("Invalid socket family. Only AF_INET or AF_INET6 is supported");
return false;
}
绑定返回-1 strerror表示发生未知错误
我传递到createSocket方法的IP地址是fe80::20c:29ff:fea0:7da8
当我通过strace运行我的程序时,我会在绑定上得到以下内容
socket(PF_INET6, SOCK_STREAM, IPPROTO_IP) = 4
bind(4, {sa_family=AF_INET6, sin6_port=htons(500), inet_pton(AF_INET6, "fe80::", &sin6_addr), sin6_flowinfo=0, sin6_scope_id=0}, 16) = -1 EINVAL (Invalid argument)
请注意,IP已被截断为fe80::
如果我不使用IP,那么它会绑定到任何IP,然后:
更新
下面是我为AF_INET6套接字更改的代码
case AF_INET6: {
this->serv_addr = new sockaddr_storage();
bzero((sockaddr_in6*)this->serv_addr, sizeof(this->serv_addr));
sockaddr_in6 *sin = reinterpret_cast<sockaddr_in6*>(serv_addr);
sin->sin6_family = family;
if (ipAddress.empty())
{
sin->sin6_addr = IN6ADDR_ANY_INIT;
}
else
{
inet_pton(AF_INET6, ipAddress.c_str(), &sin->sin6_addr);
}
sin->sin6_port = htons(port);
break;
}
案例6:{
此->serv_addr=new sockaddr_storage();
bzero((sockaddr_in6*)this->serv_addr,sizeof(this->serv_addr));
sockaddr\u in6*sin=重新解释强制转换(serv\u addr);
sin->sin6_family=family;
if(ipAddress.empty())
{
sin->sin6\u addr=IN6ADDR\u ANY\u INIT;
}
其他的
{
inet\u pton(AF\u INET6,ipAddress.c\u str(),&sin->sin6\u addr);
}
sin->sin6_端口=htons(端口);
打破
}
我还更改了此->servAddr is sockaddr\u存储在标题中的建议,至少在Windows上,
sizeof(sockaddr)
。当您为this->serv\u addr
分配内存时,分配的内存不足,然后损坏堆块,然后出现错误
建议您使用sockaddr\u存储
,它“足够大,可以容纳所有支持的特定于协议的地址结构”。或者,您可以在不同的情况下分配不同的结构,这对于代码的其余部分来说应该不是问题
更新1
您的代码中似乎仍有一些错误。您需要检查对this->serv\u addr
的所有引用,并验证类型/sizeof
--示例1:您bzero()
bzero((sockaddr_in6*)this->serv_addr, sizeof(this->serv_addr));
应该这样固定:
sockaddr_in6 *sin = reinterpret_cast<sockaddr_in6*>(serv_addr);
bzero(sin, sizeof(*sin));
您应该在分配时记住this->serv\u addr
的实际大小,并将此大小传递给bind()
至少在Windows上,sizeof(sockaddr)
。当您为this->serv\u addr
分配内存时,分配的内存不足,然后损坏堆块,然后出现错误
建议您使用sockaddr\u存储
,它“足够大,可以容纳所有支持的特定于协议的地址结构”。或者,您可以在不同的情况下分配不同的结构,这对于代码的其余部分来说应该不是问题
更新1
您的代码中似乎仍有一些错误。您需要检查对this->serv\u addr
的所有引用,并验证类型/sizeof
--示例1:您bzero()
bzero((sockaddr_in6*)this->serv_addr, sizeof(this->serv_addr));
应该这样固定:
sockaddr_in6 *sin = reinterpret_cast<sockaddr_in6*>(serv_addr);
bzero(sin, sizeof(*sin));
您应该记住分配时this->serv\u addr
的实际大小,并将此大小传递给bind()
Hmm,它已取得进展,现在可以绑定到任何地址(虽然无法通过ip6地址本地连接到它,但只能从远程计算机上工作,但如果我指定了IP地址,它在更新代码时仍会在屏幕上显示EINVAL,以便我可以看到更改。例如,不确定是否已修复sizeof(*serv\u addr)
。此外,我建议您在create()中使用IPPROTO\u TCP)
相反,如果为0。我传递到绑定中的缓冲区大小有什么问题,我在网上看到的所有内容似乎都与我拥有的内容相匹配,唯一的区别是我正在取消引用,因此它不是预期的指向结构的指针。它必须与serv\u addr
的实际大小相匹配。对于IPv6,它将是sizeof(sockaddr\u in6)
。分配时,您需要记住serv\u addr
的大小。好的,我已经尝试过了。我找到了需要设置sin6\u scope\u id
的东西,我使用sin->sin6\u scope\u id=if\u nametoindex(“eno16777728”);
现在我得到了EADDRNOTAVAIL(无法分配请求的地址)
。不确定这是否正在进行中mm,它已经进行了,现在可以绑定到任何地址(虽然无法通过ip6地址本地连接到它,但只能从远程计算机上工作,但如果我指定了IP地址,它在更新代码时仍会在屏幕上显示EINVAL,以便我可以看到更改。例如,不确定是否已修复sizeof(*serv\u addr)
。此外,我建议您在create()中使用IPPROTO\u TCP)
相反,如果为0。我传递到绑定中的缓冲区大小有什么问题,我在网上看到的所有内容似乎都与我拥有的内容相匹配,唯一的区别是我正在取消引用,因此它不是预期的指向结构的指针。它必须与serv\u addr
的实际大小相匹配。对于IPv6,它将是sizeof(sockaddr\u in6)
。分配时,您需要记住serv\u addr
的大小。好的,我已经尝试过了。我找到了需要设置sin6\u scope\u id
的东西,我使用sin->sin6\u scope\u id=if\u nametoindex(“eno16777728”);
现在我得到了EADDRNOTAVAIL(无法分配请求的地址)
。不确定这是否有进展
int result = bind(this->serverSocket, (sockaddr * )serv_addr, sizeof(*serv_addr));