Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/133.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ Can';t使用gethostbyname()获取本地IP_C++_Networking - Fatal编程技术网

C++ Can';t使用gethostbyname()获取本地IP

C++ Can';t使用gethostbyname()获取本地IP,c++,networking,C++,Networking,一位朋友使用检索其LAN中主机的本地IP地址 int buffersize = 512; char name[buffersize]; if(gethostname(name, buffersize) == -1){ Exception excep("Failed to retrieve the name of the computer"); excep.raise(); } struct hostent *hp = gethostbyname(name); if(hp ==

一位朋友使用检索其LAN中主机的本地IP地址

int buffersize = 512;
char name[buffersize];

if(gethostname(name, buffersize) == -1){
    Exception excep("Failed to retrieve the name of the computer");
    excep.raise();
}

struct hostent *hp = gethostbyname(name);
if(hp == NULL){
    Exception excep("Failed to retrieve the IP address of the local host");
    excep.raise();
}

struct in_addr **addr_list = (struct in_addr **)hp->h_addr_list;
for(int i = 0; addr_list[i] != NULL; i++) {
    qDebug() << QString(inet_ntoa(*addr_list[i]));
}
这些值看起来与适配器使用的值相似,但不同。以下是一些
ifconfig
数据:

eth0      Link encap:Ethernet  HWaddr 1C:C1:DE:91:54:1A  
          UP BROADCAST MULTICAST  MTU:1500  Metric:1
lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
wlan0     Link encap:Ethernet  HWaddr [bleep]
          inet addr:192.168.1.6  Bcast:192.168.1.255  Mask:255.255.255.0

看起来有些位被打乱了。我们缺少一个关键的转换吗?

如果您真的使用Qt,您可以使用此代码

foreach (const QHostAddress& address, QNetworkInterface::allAddresses() ) {
        qDebug() << address.toString();
    }
foreach(const QHostAddress&address,QNetworkInterface::allAddresses()){

qDebug()如果您真的使用Qt,那么可以使用以下代码

foreach (const QHostAddress& address, QNetworkInterface::allAddresses() ) {
        qDebug() << address.toString();
    }
foreach(const QHostAddress&address,QNetworkInterface::allAddresses()){

qDebug()您建议的方法依赖于一个“正确”的本地主机名和一个“正确”配置的DNS系统。我在引号中加上了“正确”,因为拥有一个未在DNS注册的本地主机名对于任何用途都是完全有效的,除了您的程序

如果您有一个已连接的套接字(或可以生成一个已连接的套接字),我建议您使用
getsockname()
查找本地IP地址。(注意:不是本地IP地址--您可以有多个。)

下面是一个这样做的示例程序。显然,大部分程序都连接到
google.com
并打印结果。只有对
getsockname()
的调用与您的问题密切相关

#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>

#include <stdio.h>
#include <errno.h>
#include <unistd.h>


int main(int ac, char **av) {
    addrinfo *res;
    if(getaddrinfo("google.com", "80", 0, &res)) {
        fprintf(stderr, "Can't lookup google.com\n");
        return 1;
    }

    bool connected = false;
    for(; res; res=res->ai_next) {
        int fd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
        if(fd < 0) {
            perror("socket");
            continue;
        }

       if( connect(fd, res->ai_addr, res->ai_addrlen) ) {
           perror("connect");
           close(fd);
           continue;
       }

       sockaddr_in me;
       socklen_t socklen = sizeof(me);
       if( getsockname(fd, (sockaddr*)&me, &socklen) ) {
           perror("getsockname");
           close(fd);
           continue;
       }

       if(socklen > sizeof(me)) {
           close(fd);
           continue;
       }

       char name[64];
       if(getnameinfo((sockaddr*)&me, socklen, name, sizeof name, 0, 0, NI_NUMERICHOST)) {
           fprintf(stderr, "getnameinfo failed\n");
           close(fd);
           continue;
        }
        printf("%s ->", name);

       if(getnameinfo(res->ai_addr, res->ai_addrlen, name, sizeof name, 0, 0, NI_NUMERICHOST)) {
           fprintf(stderr, "getnameinfo failed\n");
           close(fd);
           continue;
        }
        printf("%s\n", name);
        close(fd);
    }
}
#包括
#包括
#包括
#包括
#包括
#包括
内部主(内部ac,字符**av){
addrinfo*res;
if(getaddrinfo(“google.com”、“80”、0和res)){
fprintf(stderr,“无法查找google.com\n”);
返回1;
}
布尔连接=假;
对于(;res;res=res->ai_next){
int fd=socket(res->ai_系列,res->ai_socktype,res->ai_协议);
如果(fd<0){
佩罗(“插座”);
继续;
}
如果(连接(fd,res->ai_地址,res->ai_地址)){
perror(“连接”);
关闭(fd);
继续;
}
sockaddr_在我身上;
socklen_t socklen=尺寸(me);
if(getsockname(fd,(sockaddr*)&me和socklen)){
perror(“getsockname”);
关闭(fd);
继续;
}
if(socklen>sizeof(me)){
关闭(fd);
继续;
}
字符名[64];
if(getnameinfo((sockaddr*)&me、socklen、name、sizeof name、0、0、NI_numericost)){
fprintf(stderr,“getnameinfo失败\n”);
关闭(fd);
继续;
}
printf(“%s->”,名称);
if(getnameinfo(res->ai_addr,res->ai_addrlen,name,sizeof name,0,0,NI_numericost)){
fprintf(stderr,“getnameinfo失败\n”);
关闭(fd);
继续;
}
printf(“%s\n”,名称);
关闭(fd);
}
}

您建议的方法依赖于一个“正确”的本地主机名和一个“正确”配置的DNS系统。我在引号中加上了“正确”,因为拥有一个未在DNS注册的本地主机名对于任何用途都是完全有效的,除了您的程序

如果您有一个已连接的套接字(或可以生成一个已连接的套接字),我建议您使用
getsockname()
查找本地IP地址。(注意:不是本地IP地址--您可以有多个。)

下面是一个这样做的示例程序。显然,大部分程序都连接到
google.com
并打印结果。只有对
getsockname()
的调用与您的问题密切相关

#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>

#include <stdio.h>
#include <errno.h>
#include <unistd.h>


int main(int ac, char **av) {
    addrinfo *res;
    if(getaddrinfo("google.com", "80", 0, &res)) {
        fprintf(stderr, "Can't lookup google.com\n");
        return 1;
    }

    bool connected = false;
    for(; res; res=res->ai_next) {
        int fd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
        if(fd < 0) {
            perror("socket");
            continue;
        }

       if( connect(fd, res->ai_addr, res->ai_addrlen) ) {
           perror("connect");
           close(fd);
           continue;
       }

       sockaddr_in me;
       socklen_t socklen = sizeof(me);
       if( getsockname(fd, (sockaddr*)&me, &socklen) ) {
           perror("getsockname");
           close(fd);
           continue;
       }

       if(socklen > sizeof(me)) {
           close(fd);
           continue;
       }

       char name[64];
       if(getnameinfo((sockaddr*)&me, socklen, name, sizeof name, 0, 0, NI_NUMERICHOST)) {
           fprintf(stderr, "getnameinfo failed\n");
           close(fd);
           continue;
        }
        printf("%s ->", name);

       if(getnameinfo(res->ai_addr, res->ai_addrlen, name, sizeof name, 0, 0, NI_NUMERICHOST)) {
           fprintf(stderr, "getnameinfo failed\n");
           close(fd);
           continue;
        }
        printf("%s\n", name);
        close(fd);
    }
}
#包括
#包括
#包括
#包括
#包括
#包括
内部主(内部ac,字符**av){
addrinfo*res;
if(getaddrinfo(“google.com”、“80”、0和res)){
fprintf(stderr,“无法查找google.com\n”);
返回1;
}
布尔连接=假;
对于(;res;res=res->ai_next){
int fd=socket(res->ai_系列,res->ai_socktype,res->ai_协议);
如果(fd<0){
佩罗(“插座”);
继续;
}
如果(连接(fd,res->ai_地址,res->ai_地址)){
perror(“连接”);
关闭(fd);
继续;
}
sockaddr_在我身上;
socklen_t socklen=尺寸(me);
if(getsockname(fd,(sockaddr*)&me和socklen)){
perror(“getsockname”);
关闭(fd);
继续;
}
if(socklen>sizeof(me)){
关闭(fd);
继续;
}
字符名[64];
if(getnameinfo((sockaddr*)&me、socklen、name、sizeof name、0、0、NI_numericost)){
fprintf(stderr,“getnameinfo失败\n”);
关闭(fd);
继续;
}
printf(“%s->”,名称);
if(getnameinfo(res->ai_addr,res->ai_addrlen,name,sizeof name,0,0,NI_numericost)){
fprintf(stderr,“getnameinfo失败\n”);
关闭(fd);
继续;
}
printf(“%s\n”,名称);
关闭(fd);
}
}

我在Windows(VS2010;因此未使用异常和QString)上测试了您的代码,它返回的IP地址值正常。可能我的主机保存某些数据的方式有所不同?我被告知网络有一种普遍认可的表示数据的方式,这就是为什么您必须执行“网络到主机”和“主机到网络”的原因在某些事情上的转换。
inet\u ntoa
被证明是不推荐的。但是,如何解码
addr\u list
中的每个字符串,根据手册页是按网络字节顺序编码的,回到主机顺序?我尝试了
ntohs()
在每个字符上,但这并没有达到预期的结果。可能的重复有很多人建议您找到的解决方案。他们错了——使用gethostname()和gethostbyname()不是很可靠。请尝试以下答案:,或调用连接的套接字。我在Windows上测试了您的代码(VS2010;所以没有使用Exception和QString)并返回IP地址的ok值。可能主机保存某些数据的方式有所不同?我被告知网络有一种普遍认可的表示数据的方式,这就是为什么