这段代码定义了一个成员函数 _setAddr
,它的作用是设置一个 sockaddr_in
结构体,以便用于网络编程中建立 TCP 或 UDP 连接。下面对代码进行逐行分析并解释其功能。
函数解析
void CBaseSocket::_setAddr(const char* ip, const uint16_t port, sockaddr_in* addr) {
CBaseSocket
是类名,表示该函数是这个类的一个成员。- 函数接收三个参数:
const char* ip
: 字符串形式的 IP 地址,可以是 IPv4 地址或主机名。const uint16_t port
: 端口号,使用无符号 16 位整数表示。sockaddr_in* addr
: 指向sockaddr_in
结构体的指针,该结构体将被填充以包含目标地址信息。
功能实现
memset(addr, 0, sizeof(sockaddr_in));
- 清空传入的
sockaddr_in
结构体,将所有字节设置为零。这是初始化步骤,以确保没有遗留数据。
addr->sin_family = AF_INET;
- 设置地址族为 IPv4(即 AF_INET)。
addr->sin_addr.s_addr = inet_addr(ip);
- 将字符串形式的 IP 地址转换为网络字节顺序的二进制格式,并赋值给
sin_addr.s_addr
。如果传入的是合法的 IP 地址,则会正确转换;如果不是,会返回 INADDR_NONE。
if (addr->sin_addr.s_addr == INADDR_NONE) {
hostent* host = gethostbyname(ip);
if (host == nullptr) {
LogErr("gethostbyname failed, ip=%s, port=%u", ip, port);
return;
}
addr->sin_addr.s_addr = *(uint32_t*)host->h_addr;
}
错误处理:
- 如果调用
inet_addr(ip)
返回INADDR_NONE
,说明输入可能不是有效的 IP 地址。 - 在这种情况下,尝试使用 DNS 查询将主机名转换为 IP 地址,通过调用
gethostbyname()
。该函数会返回一个指向hostent
的指针,其中包含解析后的地址信息。 - 如果 DNS 查询失败(即返回 nullptr),则通过日志记录错误信息并退出函数。
- 如果调用
获取到主机名后:
- 将查询得到的第一个地址 (
host->h_addr
) 转换为大端字节顺序并赋值给sin_addr.s_addr
。
- 将查询得到的第一个地址 (
总结
这段代码提供了一种灵活的方法来设置网络连接所需的地址和端口。如果提供的是有效的 IP 地址,它将直接使用它;如果提供的是主机名,则将其解析成对应的 IP 地址。此过程在很多网络应用中非常常见,用于建立 socket 通信前配置目标地址。
内容由零声教学AI助手提供,问题来源于学员提问