使用unix套接字获取本地ip地址
Get the local ip address with unix sockets
我正在编程一个简单的UDP客户端-服务器聊天,以更熟悉网络编程。现在,为了让用户更容易地查看服务器的IP地址(这样用户就可以将其输入到客户端进行连接)。这就是为什么我希望服务器显示自己的本地IP地址。
这是我的代码:(编辑代码以处理多个IP)
// 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,但它不是正确的。正如我所说,我还在学习网络编程,所以我不知道为什么。有人能给我指明正确的方向吗?
Soo,多亏了我在这里得到的建议,我改变了方法,不再试图将机器的主机名解析为IP地址,而是简单地列出所有网络接口及其IP地址。
这是我的代码:
// 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
您将无法获得这样的"全局"IP地址,只能获得本地地址。为了让客户端连接到您,它需要从互联网上可见的全局IP地址,即您的网关(路由器)的IP。这是因为路由器将计算机的IP地址转换为全局可见的IP地址,并将其存储在表中,以便将传入连接正确路由到正确的子网络。这被称为NATing(点击此处了解有关NAT的更多信息)。
如果您希望客户端显式连接到您,则需要向他们提供路由器的IP地址(根据您的操作系统,使用命令行工具),并配置端口转发,以便路由器自动将到达(IP_router,port_router)的数据包转发到(IP_host,port_host)。这是在路由器的配置面板中完成的。根据您的路由器,这将在菜单中的某个位置找到。您可以通过键入类似192.068.0.1
或192.168.0.0
的内容来连接到路由器。
在Windows上,您可以使用gethostbyname
并通过hostent
h_addr_list
枚举。。。在Linux上,您可以创建一个临时套接字,在SIOCGIFCONF
上使用ioctl
并通过接口枚举。
我认为在代码的末尾,您滥用了数据结构sockaddr_in。线路:
inet_ntop(AF_INET, &(serverInfo->ai_addr), serverIPAddress, INET_ADDRSTRLEN);
应替换为:
struct sockaddr_in *ipv4 = (struct sockaddr_in *)serverInfo->ai_addr;
void *addr = &(ipv4->sin_addr);
inet_ntop(AF_INET, addr, serverIPAddress, INET_ADDRSTRLEN);
// Get a Vector of the IP addresses of this computer
std::vector<std::string> getIPAddresses() {
std::vector<std::string> IPAddresses;
int TempAddress = 0;
char* TempIPAddress = (char*) malloc(16);
ifaddrs* ifap = NULL; //Head of the interface address linked list
if (getifaddrs(&ifap) == 0 && ifap != NULL) {
//Get another pointer to move down the linked list
ifaddrs* current = ifap;
//Move down the linked list until we get to a NULL pointer
while (current != NULL) {
//Create a pointer of the correct type to work with
const sockaddr_in* interfaceAddress = reinterpret_cast<const sockaddr_in*>(current->ifa_addr);
if (current->ifa_addr != NULL) {
if (current->ifa_addr->sa_family == AF_INET) {
//printf("%s:", current->ifa_name);
if (interfaceAddress != NULL) {
TempAddress = ntohl(interfaceAddress->sin_addr.s_addr);
sprintf(TempIPAddress, "%d.%d.%d.%d", (TempAddress >> 24) & 0xFF, (TempAddress >> 16) & 0xFF,
(TempAddress >> 8) & 0xFF, TempAddress & 0xFF);
//Don't include the lookback address
if (strcmp(TempIPAddress, "127.0.0.1") != 0) {
IPAddresses.push_back(std::string(TempIPAddress));
}
//printf("%sn", TempIPAddress);
}
}
}
//Move to the next node in the linked-list
current = current->ifa_next;
}
//Release the interface memory
freeifaddrs(ifap);
ifap = NULL;
}
return IPAddresses;
}
- 如何使用 Boost Asio 在 Android 上获取我的本地 udp IP 地址?
- C++ / Qt:如何检测主机名或IP地址何时引用当前系统?
- 使用 C++将 IP 地址附加到字符*
- 使用全局 IP 地址时,C++ winsock 2 应用程序中的代码是否必须更改?
- Rabbitmq 将本地主机更改为 IP 地址C++
- C++ - 使用代码块从文件中读取 IP 地址
- C 使用from_string创建IP地址的C 导致lambda错误
- 如何在解析过程中区分 IP 地址和域名
- 如何使用 asio 库获取 IP 地址的主机名
- IP地址匹配过滤功能
- 如何将C++ ulong 4 字节 IP 地址正确转换为 C# 类型
- 如何在NS3中设置节点的IP地址和数据?
- 如何从活动的 udp 连接获取远程 IP 地址和端口
- 无符号的 int 到 IP 地址字符串,不带 itoa/to_string/boost
- 如何在FD_SET内获取套接字的IP地址
- 使用Boost库中的PC中获取我的以太网设备IP地址的列表
- 使用静态IP地址时,ESP32 httpclient连接拒绝了
- C++检查有效的 IP 地址或 IP
- 如何使用 Poco::Net::HTTPSClientSession 绑定特定的源 IP 地址
- 如何在Windows上绕过主机文件获取真实的IP地址