首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用unix套接字获取本地ip地址。

使用unix套接字获取本地ip地址。
EN

Stack Overflow用户
提问于 2014-11-11 12:20:36
回答 5查看 2.3K关注 0票数 0

我正在编写一个简单的UDP客户端服务器聊天程序,以便更熟悉网络编程。现在,为了让用户更容易地查看服务器IP地址(因此用户可以将其键入客户机进行连接)。这就是为什么我希望服务器显示自己的本地IP地址。

这是我的代码:(处理多个IP的编辑代码)

代码语言:javascript
复制
// get the hostname of the server
char hostname[128];
if (gethostname(hostname, sizeof(hostname)) == -1) {
    std::cout << "Could not get the hostname of the server. Error: " << std::strerror(errno) << std::endl;
    return 1;
}

struct addrinfo hints, *serverInfo, *p;

std::memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC; // use AF_INET (IPv4) or AF_INET6 (IPv6) to force version
hints.ai_socktype = SOCK_DGRAM;

// try to get information about our hostname
int rv;
if ((rv = getaddrinfo(hostname, NULL, &hints, &serverInfo)) != 0) {
    std::cout << "Failed to get information about the host \"" << hostname << "\". Error: " << gai_strerror(rv) << std::endl;
    return 1;
}

std::cout << "IP addresses for " << hostname << ":" << std::endl;

// iterate over all the infos we got and try to extract the IP address
for(p = serverInfo; p != NULL; p = p->ai_next) {
    char serverIPAddress[INET6_ADDRSTRLEN];
    void *addr;
    std::string ipVersion;

    // get the pointer to the address itself,
    // different fields in IPv4 and IPv6:
    if (p->ai_family == AF_INET) { // IPv4
        struct sockaddr_in *ipv4 = (struct sockaddr_in *)p->ai_addr;
        addr = &(ipv4->sin_addr);
        ipVersion = "IPv4";
    } else { // IPv6
        struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)p->ai_addr;
        addr = &(ipv6->sin6_addr);
        ipVersion = "IPv6";
    }

    // take the IP address of our hostname and convert it into a readable format
    inet_ntop(p->ai_family, addr, serverIPAddress, sizeof(serverIPAddress));
    std::cout << "  " << ipVersion << ": " << serverIPAddress << std::endl;
}

freeaddrinfo(serverInfo); // free the linked list

它工作,但它没有显示正确的IP地址。每次我运行它时,都会显示一个不同的IP,而且它不是正确的。正如我说的,我仍然在学习网络编程,所以我不知道为什么。谁能给我指明正确的方向吗?

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2014-11-12 23:24:21

Soo,感谢我在这里得到的建议,我改变了我的方法,不再试图将我的机器的主机名解析为IP地址,现在我只是简单地列出了所有的网络接口及其IP地址。

这是我的代码:

代码语言:javascript
复制
// get the hostname of the server
char hostname[128];
if (gethostname(hostname, sizeof(hostname)) == -1) {
    std::cout << "Could not get the hostname of the server. Error: " << std::strerror(errno) << std::endl;
    return 1;
}

std::cout << "IP addresses for " << hostname << ":" << std::endl << std::endl;

struct ifaddrs *networkInterfaceList, *p;

getifaddrs (&networkInterfaceList); // get information about the network interfaces

// iterate over all the network interfaces we got and try to extract their IP address
for (p = networkInterfaceList; p != NULL; p = p->ifa_next) {
    char serverIPAddress[INET6_ADDRSTRLEN];
    void *addr;
    std::string ipVersion;

    // get the pointer to the address itself,
    // different fields in IPv4 and IPv6:
    if (p->ifa_addr->sa_family == AF_INET) { // IPv4
        struct sockaddr_in *ipv4 = (struct sockaddr_in *)p->ifa_addr;
        addr = &(ipv4->sin_addr);
        ipVersion = "IPv4";
    } else { // IPv6
        struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)p->ifa_addr;
        addr = &(ipv6->sin6_addr);
        ipVersion = "IPv6";
    }

    // take the IP address of our hostname and convert it into a readable format
    inet_ntop(p->ifa_addr->sa_family, addr, serverIPAddress, sizeof(serverIPAddress));

    // sometime the IP address is empty so only print if there is one
    if (std::strlen(serverIPAddress) > 0)
        std::cout << "Interface: " << std::setw(6) << std::left << p->ifa_name << " " << ipVersion << ": " << serverIPAddress << std::endl;
}

freeifaddrs(networkInterfaceList); // free the linked list

以防万一别人也在尝试类似的东西。

此外,如果有人感兴趣,这里是聊天回购:https://github.com/Foaly/Chat

票数 1
EN

Stack Overflow用户

发布于 2014-11-11 12:45:50

您将无法获得这样的“全局”IP地址,只有本地地址。为了让客户端连接到您,它需要全局IP地址,该地址在Internet上是可见的,即网关的(路由器) IP。这是因为路由器将计算机的IP地址转换为全局可见的地址,并将其存储在表中,以便将传入的连接正确路由到正确的子网络。这称为_NAT_ing (了解更多关于NAT 这里的信息)。

如果您希望客户端连接到您的显式,您需要给他们路由器的IP地址(根据您的操作系统使用命令行工具),并配置端口转发,以便路由器将到达的数据包(IP_router、port_router)自动转发到(IP_host、port_host)。这是在路由器的配置面板中完成的。根据您的路由器,这将在菜单中的某个地方找到。您可以通过键入类似于192.068.0.1192.168.0.0的内容来连接到路由器。

票数 0
EN

Stack Overflow用户

发布于 2014-11-11 12:57:48

在Windows上,您可以使用gethostbyname并通过hostent h_addr_list枚举.在Linux上,您可以创建一个临时套接字,并在ioctl上使用SIOCGIFCONF并通过接口进行枚举。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/26864815

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档