问题
最近有个任务,需要把公司的各个检测引擎做成docker虚拟机,使用docker-compose管理,在各个虚拟机之间使用桥模式搭建虚拟网络,各个检测引擎通过虚拟网络通讯。具体搭建过程以后给大家分享,不是这篇文章的重点。
后来发现一个问题:
之前各服务的端口都是监听在本地(127.0.0.1)的,而在服务配置之间通讯有些直接使用的TCP套接字(socket通讯),所以在客户端直接使用 connect 127.0.0.1 这个地址就可以了。但是现在需要将各个检测引擎 通过虚拟网络通讯,而各个检测引擎虚拟机的 IP地址是未知的,而各个检测引擎虚拟机的主机名是已知的,因为主机名可以通过 docker-compose 配置来设置固定主机名。
所以:
我就去修改C代码,增加主机名或者域名解析成IP地址的方法,顺便整理了给大家分享一下。以后用着了,直接copy就能用了。
talk is cheap, show me the code!!
// getaddrinfo.c
// gcc -Wall getaddrinfo.c -o test
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>
/**
* @brief 给定一个主机名或者域名,把主机名能解析到的IPv4和IPv6给出来
*
* @param hostname 主机名/域名
* @param (* ip_list 解析结果,是一个数组,内部有 申请空间,如果不为空,需要free
*
* @return 返回解析到的IP地址的数量
*/
int get_ip_by_hostname( char *hostname, char (* (* ip_list) )[INET6_ADDRSTRLEN]) {
struct addrinfo hints; // 设置查询条件
struct addrinfo *res; // 指向结果链表的指针
int status;
int count = 0 ; // 解析到的 ip 数量
char ipstr[INET6_ADDRSTRLEN] ;
char (*ip_rslt)[INET6_ADDRSTRLEN] = NULL ;
// 设置查询条件
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC; // 支持 IPv4 和 IPv6
hints.ai_socktype = SOCK_STREAM; // TCP 流式套接字
// 查询 host 、 DNS 等
if ((status = getaddrinfo(hostname, NULL, &hints, &res)) != 0) {
fprintf(stderr, "getaddrinfo error: %s\n", gai_strerror(status));
return -1 ;
}
struct addrinfo *p;
for (p = res; p != NULL; p = p->ai_next) {
void *addr;
// 获取地址结构
if (p->ai_family == AF_INET) { // IPv4
struct sockaddr_in *ipv4 = (struct sockaddr_in *)p->ai_addr;
addr = &(ipv4->sin_addr);
} else { // IPv6
struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)p->ai_addr;
addr = &(ipv6->sin6_addr);
}
++count ;
// 将网络地址转换为字符串
inet_ntop(p->ai_family, addr, ipstr, sizeof(ipstr));
// 申请空间,解析数据
ip_rslt = (char (*) [INET6_ADDRSTRLEN]) realloc (ip_rslt, count* INET6_ADDRSTRLEN) ;
snprintf(ip_rslt[count-1], INET6_ADDRSTRLEN, "%s", ipstr ) ;
}
*ip_list = ip_rslt ;
// 释放资源
freeaddrinfo(res);
return count;
}
/**
* @brief 测试
*
* @return
*/
int main() {
int count = 0 ;
char (*ip_rslt)[INET6_ADDRSTRLEN] = NULL ;
// 测试一
char * hostname = "node9" ;
count = get_ip_by_hostname(hostname, &ip_rslt) ;
printf("IP addresses for %s:\n", hostname);
for( int i = 0 ; i < count ; ++i ) {
printf(" %d: %s\n", i+1, ip_rslt[i]);
}
if(ip_rslt) free(ip_rslt) ;
ip_rslt = NULL ;
// 测试二
hostname = "localhost" ;
count = get_ip_by_hostname(hostname, &ip_rslt) ;
printf("IP addresses for %s:\n", hostname);
for( int i = 0 ; i < count ; ++i ) {
printf(" %d: %s\n", i+1, ip_rslt[i]);
}
if(ip_rslt) free(ip_rslt) ;
ip_rslt = NULL ;
// 测试三
hostname = "www.163.com" ;
count = get_ip_by_hostname(hostname, &ip_rslt) ;
printf("IP addresses for %s:\n", hostname);
for( int i = 0 ; i < count ; ++i ) {
printf(" %d: %s\n", i+1, ip_rslt[i]);
}
if(ip_rslt) free(ip_rslt) ;
ip_rslt = NULL ;
}
测试
其中 主机 node9 是在 /etc/hosts 中配置的。

发表回复