【问题标题】:how do you cast sockaddr structure to a sockaddr_in - C++ networking sockets ubuntu UDP你如何将 sockaddr 结构转换为 sockaddr_in - C++ 网络套接字 ubuntu UDP
【发布时间】:2012-07-25 21:47:29
【问题描述】:

我正在尝试获取客户端地址,但我不确定如何将 sockaddr 结构转换为 sockaddr_in?

struct sockaddr_in cliAddr, servAddr;

    n = recvfrom(sd, msg, MAX_MSG, 0,(struct sockaddr *) cliAddr,sizeof(cliAddr));

 //i tried this but it does not work
    struct sockaddr cliSockAddr = (struct sockaddr *) cliAddr; 
    char *ip = inet_ntoa(cliSockAddr.sin_addr);

提前致谢! :)


我发现了一些让我走到这一步的问题: Getting IPV4 address from a sockaddr structure


抱歉,避免混淆,这是我的真实实现,其中“ci”是存储指针的对象,例如 sockaddr_in。

    /* receive message */
    n = recvfrom(*(ci->getSd()), msg, MAX_MSG, 0,(struct sockaddr *) ci->getCliAddr(),ci->getCliLen());

    char *ip = inet_ntoa(ci->getCliAddr().sin_addr);

我会得到以下错误:

udpserv.cpp:166: error: request for member ‘sin_addr’ in ‘ci->clientInfo::getCliAddr()’, which is of non-class type ‘sockaddr_in*’

【问题讨论】:

  • 您的代码甚至无法编译。您正在分配一个指向结构的指针,将cliSockAddr 声明为指针。
  • 您真正要问的是与标题中所说的相反。

标签: c++ sockets networking ubuntu client


【解决方案1】:

其实很简单!

struct sockaddr *sa = ...;

if (sa->sa_family == AF_INET)
{
    struct sockaddr_in *sin = (struct sockaddr_in *) sa;
    ip = inet_ntoa(sin->sin_addr);
}

【讨论】:

  • 当你这样做的时候,通过检查 AF_INET6 来让你的程序支持 IPv6。 ;)
  • 我知道这是一个旧线程,但为了正确起见,@bmatheny 下面的答案是正确的,因为这个问题被标记为“C++”。 reinterpret_cast<sockaddr_in*>(sa) 是转换这两种类型的正确方法,虽然旧的 C 转换仍然有效,但它太晦涩难懂,不会让任何读者明白其意图。
【解决方案2】:

我认为这对你来说编译得很好,做你想做的事。

struct sockaddr_in cliAddr={}, servAddr={};

socklen_t cliAddrLength = sizeof(cliAddr);

n = recvfrom(sd, msg, MAX_MSG, 0,(struct sockaddr *)&cliAddr, &cliAddrLength);

【讨论】:

    【解决方案3】:

    我会指出,如果这实际上是 C++,那么惯用的做法是:

    sockaddr *sa = ...; // struct not needed in C++
    char ip[INET6_ADDRSTRLEN] = {0};
    
    switch (sa->sa_family) {
      case AF_INET: {
        // use of reinterpret_cast preferred to C style cast
        sockaddr_in *sin = reinterpret_cast<sockaddr_in*>(sa);
        inet_ntop(AF_INET, &sin->sin_addr, ip, INET6_ADDRSTRLEN);
        break;
      }
      case AF_INET6: {
        sockaddr_in6 *sin = reinterpret_cast<sockaddr_in6*>(sa);
        // inet_ntoa should be considered deprecated
        inet_ntop(AF_INET6, &sin->sin6_addr, ip, INET6_ADDRSTRLEN);
        break;
      }
      default:
        abort();
    }
    

    此示例代码处理 IPv4 和 IPv6 地址,并且被认为比任何建议的实现都更符合 C++ 习惯。

    【讨论】:

    • 我真的很喜欢你使用了 reinterpret_cast。它使一切都变得更加干净,并且需要使用的指针更少。在旁注中,我没有将 sa 设置为开始的指针。我只是像这样通过引用将地址传递给它(我的是一个学校项目,只使用 IPv4 -- inet_ntoa(reinterpret_cast(&clientIpAddress)->sin_addr)
    猜你喜欢
    • 2021-05-18
    • 1970-01-01
    • 1970-01-01
    • 2015-06-21
    • 2017-01-15
    • 2012-07-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多