【问题标题】:How to copy the 4 bytes to sockaddr.sa_data?如何将 4 个字节复制到 sockaddr.sa_data?
【发布时间】:2020-07-31 23:12:35
【问题描述】:

根据https://stackoverflow.com/a/5328190,我可以使用

std::string ip ="192.168.1.54";
std::stringstream s(ip);
int a,b,c,d; //to store the 4 ints
char ch; //to temporarily store the '.'
s >> a >> ch >> b >> ch >> c >> ch >> d;
std::cout << a << "  " << b << "  " << c << "  "<< d;

将 IP 转换为其 4 个字节。但是我如何把它们放在一个

struct sockaddr
  {
    __SOCKADDR_COMMON (sa_);    /* Common data: address family and length.  */
    char sa_data[14];       /* Address data.  */
  };

?

我应该只是简单地复制sa_data的前4个字节中的4个字节吗?

【问题讨论】:

    标签: c++ c sockets networking


    【解决方案1】:

    您实际上并没有直接使用struct sockaddr。您将改为填充一个用于保存 IPv4 地址和端口的 struct sockaddr_in,然后将该结构的地址传递给需要 struct sockaddr * 的函数。

    要从 C 字符串填充 sockaddr_in 的地址字段,您可以使用 inet_addr。

    例如:

    struct sockaddr_in sin;
    sin.sin_family = AF_INET;
    sin.sin_addr.s_addr = inet_addr(ip.c_str());
    sin.sin_port = 0;
    

    在调用recvfrom 时,addrlen 参数应该是一个指向变量的指针,该变量设置为src_addr 参数指向的结构的大小。例如:

    struct sockaddr_in peerAddr;
    socklen_t len = sizeof(peerAddr);
    recvfrom(sock, data, capacity, 0, (struct sockaddr *)&peerAddr, &len);
    

    【讨论】:

    • 谢谢!所以我应该把它传递给一个指向sockaddr的指针?我怎样才能像recvfrom(sock, data, capacity, 0, &amp;peerAddr, &amp;len); 填充len 一样填充长度?我应该只做len = sizeof sin 吗?我开了一个赏金,请帮助我
    【解决方案2】:

    更好的方法是使用getaddrinfo,例如

    struct addrinfo params = { 0 };
    params.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV; // adjust
    params.ai_family = AF_UNSPEC;
    params.ai_socktype = SOCK_STREAM; // adjust
    params.ai_protocol = IPPROTO_TCP; // adjust
    
    struct addrinfo *addrs;
    int status = getaddrinfo(ip.c_str(), port.c_str(), &params, &addrs);
    if (status == EAI_SYSTEM) {
      fprintf(stderr, "%s:%s: %s\n", ip.c_str(), port.c_str(), strerror(errno));
      return -1;
    } else if (status) {
      fprintf(stderr, "%s:%s: %s\n", ip.c_str(), port.c_str(), gai_strerror(status));
      return -1;
    }
    for (struct addrinfo *ai = addrs; ai; ai = ai->ai_next) {
      // do something with ai->ai_addr etc here
    }
    freeaddrinfo(addrs);
    return 0;
    

    您需要为您的应用程序调整标记为“调整”的行。您还需要提供一个端口号(不方便的是,它将它作为一个字符串,因为它也可以接受一个协议名称)。

    这样做的好处是:addrs 链表中的每个条目都包含创建套接字并将套接字连接到该地址所需的所有数据;它为您无缝处理 IPv6;而且,如果您取出AI_NUMERICHOST,它也会为您无缝处理域名。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-06-09
      • 1970-01-01
      • 1970-01-01
      • 2015-01-11
      • 2014-03-27
      • 2011-09-16
      • 1970-01-01
      相关资源
      最近更新 更多