我正在开发一个后效插件,我正在尝试集成raknet这是一个c ++网络库。当raknet库试图通过调用
来获取ipv4地址时gethostbyname
然后抛出错误访问冲突读取位置0xFFFFFFFFFFFFFFFF
int idx=0;
char ac[ 80 ];
int err = gethostname( ac, sizeof( ac ) );
(void) err;
RakAssert(err != -1);
struct hostent *phe = gethostbyname( ac );
if ( phe == 0 )
{
RakAssert(phe!=0);
return ;
}
for ( idx = 0; idx < MAXIMUM_NUMBER_OF_INTERNAL_IDS; ++idx )
{
if (phe->h_addr_list[ idx ] == 0)
break;
memcpy(&addresses[idx].address.addr4.sin_addr,phe->h_addr_list[ idx ], sizeof(struct in_addr));
}
while (idx < MAXIMUM_NUMBER_OF_INTERNAL_IDS)
{
addresses[idx]=UNASSIGNED_SYSTEM_ADDRESS;
idx++;
}
以下是我看到的一些照片。
http://jacobsgriffith.com/stackoverflow/noaccesserror.png
我已经读过这篇文章了,看起来它并没有像库那样错误。 Microsoft Documentation On gethostbyname
当我将鼠标悬停在h_addr_list和h_aliases上时,我得到了。
http://jacobsgriffith.com/stackoverflow/noaccess.jpg
有人有什么想法吗?为什么这个失败我很确定这是一个常见的功能。
另一件事,winsock和winsock2的gethostbyname函数的实现有什么区别吗?
答案 0 :(得分:1)
我很惊讶Windows实现不是线程安全的,并且为每个hostent使用线程本地存储。但无论如何......
只需使用getaddrinfo即可解析主机名。它是线程安全的,可以替代gethostname。
但你的最终目标是枚举盒子上的本地IP地址。在这种情况下,只需在UNIX上使用getifaddrs,在Windows上使用GetAdaptersInfo and GetAdatperAddresses的组合来枚举本地IP地址。您也可以在Windows上使用带有虚拟套接字的SIO_ADDRESS_LIST_QUERY ioctl。
答案 1 :(得分:0)
这是我提出的解决方案。 显然gethostname不是线程安全的。效果是多线程的。
我替换了这个
int idx=0;
char ac[ 80 ];
int err = gethostname( ac, sizeof( ac ) );
(void) err;
RakAssert(err != -1);
struct hostent *phe = gethostbyname( ac );
if ( phe == 0 )
{
RakAssert(phe!=0);
return ;
}
for ( idx = 0; idx < MAXIMUM_NUMBER_OF_INTERNAL_IDS; ++idx )
{
if (phe->h_addr_list[ idx ] == 0)
break;
memcpy(&addresses[idx].address.addr4.sin_addr,phe->h_addr_list[ idx ],sizeof(struct in_addr));
}
while (idx < MAXIMUM_NUMBER_OF_INTERNAL_IDS)
{
addresses[idx]=UNASSIGNED_SYSTEM_ADDRESS;
idx++;
}
用这个
int idx=0;
struct addrinfo* feed_server = NULL;
struct addrinfo hints;
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_INET;
getaddrinfo("localhost", NULL, &hints, &feed_server);
struct addrinfo *res;
for(res = feed_server; res != NULL; res = res->ai_next) {
struct sockaddr_in* saddr = (struct sockaddr_in*)res->ai_addr;
//char* ipv4Str = inet_ntoa(saddr->sin_addr);
memcpy(&addresses[idx].address.addr4.sin_addr, &saddr->sin_addr, sizeof(struct in_addr));
idx++;
}
while (idx < MAXIMUM_NUMBER_OF_INTERNAL_IDS) {
addresses[idx]=UNASSIGNED_SYSTEM_ADDRESS;
idx++;
}
这就是我走那条路的原因。有人反对吗?