【问题标题】:Extracting IP Address and Port Info from sockaddr_storage从 sockaddr_storage 中提取 IP 地址和端口信息
【发布时间】:2012-09-30 09:46:42
【问题描述】:

我目前正在使用接收来自客户端的请求的 UDP 服务器。我收到的数据报是一个 5 个元素长的字节 (char) 数组,最后两个元素是端口号。

最终,该服务器必须在自己的数据报中返回 IP 地址和端口号。

我已经知道如何使用 inet_ntop 和我连接并从中接收到的 sockaddr 结构来打印出 ip,但它返回的字符串不是我想要的格式。例如:

string1 = inet_ntop(their_addr.ss_family,get_in_addr(
    (struct sockaddr *)&their_addr),s, sizeof s);

返回:

127.0.0.1

或:

[1][2][7][.][0][.][0][.][1]

当我需要类似的东西时:

[127][0][0][1]

我应该使用某种字符和数组操作来制作我的 4 元素字节数组吗?或者 sockaddr 是否以某种方式拥有这些信息,我可以将其保留为这种十六进制形式并返回它?

【问题讨论】:

    标签: c arrays sockets udp ip-address


    【解决方案1】:

    假设为 IPv4。

    在获取 sockaddr_storage 或 sockaddr 结构的地址并将其转换为 IPv4 版本 sockaddr_in 后,您可以访问 IPv4 地址的各个字节。

    struct sockaddr_in *sin = (struct sockaddr_in *)&their_addr;
    

    然后您可以获取 s_addr 成员的地址,它是一个 32 位值 (in_addr_t),它包含 4 个字节的 IP 地址(按网络字节顺序),并将其转换为指向 @987654327 的指针@ 然后允许您访问值的各个字节。

    unsigned char *ip = (unsigned char *)&sin->sin_addr.s_addr;
    
    printf("%d %d %d %d\n", ip[0], ip[1], ip[2], ip[3]);
    

    【讨论】:

    • 这正是我想要的。简洁而优秀。谢谢@Kludas
    【解决方案2】:

    您可能想使用getnameinfo() 函数:

    int getnameinfo(const struct sockaddr *sa, socklen_t salen,
                       char *host, size_t hostlen,
                       char *serv, size_t servlen, int flags);
    

    例如:

    struct sockaddr_storage client_addr;
    socklen_t client_len = sizeof(struct sockaddr_storage);
    
    /* Accept client request */
    int client_socket = accept(server_socket, 
        (struct sockaddr *)&client_addr, &client_len);
    
    char hoststr[NI_MAXHOST];
    char portstr[NI_MAXSERV];
    
    int rc = getnameinfo((struct sockaddr *)&client_addr, 
        client_len, hoststr, sizeof(hoststr), portstr, sizeof(portstr), 
        NI_NUMERICHOST | NI_NUMERICSERV);
    
    if (rc == 0) 
        printf("New connection from %s %s", hoststr, portstr);
    

    【讨论】:

      【解决方案3】:

      这是一个简单的不可变类,我用于您在问题中提到的相同目的:

      class address_t {
      
      private:
          uint16_t m_Port = 0;
          std::string m_Ip = "";
      
      public:
          address_t(const sockaddr_in & address) {
              m_Ip = inet_ntoa(address.sin_addr);
              m_Port = ntohs(address.sin_port);
          }
      
          uint16_t GetPort() const { return m_Port; }
          std::string GetIp() const { return m_Ip; }
          std::string ToString() const {
              return "IP: " + m_Ip + ", Port: " + std::to_string(m_Port);
          }
      };
      

      【讨论】:

        猜你喜欢
        • 2014-07-29
        • 1970-01-01
        • 2011-11-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-08-19
        • 2014-12-29
        • 2014-03-14
        相关资源
        最近更新 更多