ZBLOG

void CBaseSocket::_setAddr(const char* ip, const uint16_t port, sockaddr_in* addr) { memset(addr, 0, sizeof(sockaddr_in)); addr->sin_family = AF_INET; addr->sin_addr.s_addr = inet_addr(ip); addr->sin_port = htons(port); if (add...

这段代码定义了一个成员函数 _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助手提供,问题来源于学员提问

本站部分文章来源于网络,版权归原作者所有,如有侵权请联系站长删除。
转载请注明出处:https://golang.0voice.com/?id=19586

分享:
扫描分享到社交APP
上一篇
下一篇
发表列表
游客 游客
此处应有掌声~
评论列表

还没有评论,快来说点什么吧~

联系我们

在线咨询: 点击这里给我发消息

微信号:3007537140

上班时间: 10:30-22:30

关注我们
x

注册

已经有帐号?