相关疑难解决方法(0)

sockaddr,sockaddr_in和sockaddr_in6有什么区别?

我知道sockaddr_in用于IPv4,sockaddr_in6用于IPv6.我的困惑是sockaddr和sockaddr_in之间的区别[6].

有些函数接受sockaddr,有些函数接受sockaddr_insockaddr_in6,所以:

  • 规则是什么?
  • 为什么需要两种不同的结构?

而且因为sizeof(sockaddr_in6) > sizeof(sockaddr) == sizeof(sockaddr_in).

  • 这是否意味着如果我们需要支持ipv4和ipv6,我们应该总是使用sockaddr_in6在堆栈中分配内存并转换为sockaddr和sockaddr_in?

一个例子是:我们有一个套接字,我们想得到它的字符串IP地址(它可以是ipv4或ipv6).

我们首先打电话getsockname来获得一个addr然后inet_ntop基于的电话addr.sa_family.

这段代码片段有什么问题吗?

char ipStr[256];
sockaddr_in6 addr_inv6;
sockaddr* addr = (sockaddr*)&addr_inv6;
sockaddr_in* addr_in = (sockaddr_in*)&addr_inv6;

socklen_t len = sizeof(addr_inv6);
getsockname(_socket, addr, &len);

if (addr->sa_family == AF_INET6) {
    inet_ntop(addr_inv6.sin6_family, &addr_inv6.sin6_addr, ipStr, sizeof(ipStr)); 
    // <<<<<<<<IS THIS LINE VALID, getsockname expected a sockaddr, but we use 
    // it output parameter as sockaddr_in6.
} else {
    inet_ntop(addr_in->sin_family, &addr_in->sin_addr, …
Run Code Online (Sandbox Code Playgroud)

c c++ api network-programming

42
推荐指数
2
解决办法
3万
查看次数

将围绕sockaddr_storage和sockaddr_in强制转换为严格别名

按照我之前的问题,我对这段代码非常好奇 -

case AF_INET: 
    {
        struct sockaddr_in * tmp =
            reinterpret_cast<struct sockaddr_in *> (&addrStruct);
        tmp->sin_family = AF_INET;
        tmp->sin_port = htons(port);
        inet_pton(AF_INET, addr, tmp->sin_addr);
    }
    break;
Run Code Online (Sandbox Code Playgroud)

在提出这个问题之前,我已经搜索了关于同一主题的SO,并对此主题进行了混合回答.例如,看到这个,这个这个帖子说,使用这种代码在某种程度上是安全的.还有另一篇文章说使用工会来完成这样的任务,但是对接受的答案的评论再次提出不同意见.


微软关于相同结构的文档说 -

应用程序开发人员通常只使用SOCKADDR_STORAGE的ss_family成员.其余成员确保SOCKADDR_STORAGE可以包含IPv6或IPv4地址,并且适当填充结构以实现64位对齐.这种对齐使协议特定的套接字地址数据结构能够访问SOCKADDR_STORAGE结构中的字段而不会出现对齐问题.通过填充,SOCKADDR_STORAGE结构的长度为128个字节.

Opengroup的文件说明 -

标题应定义sockaddr_storage结构.该结构应为:

足够大以容纳所有支持的协议特定的地址结构

在适当的边界对齐,以便指向它的指针可以作为指向协议特定地址结构的指针,并用于访问这些结构的字段而没有对齐问题

socket的 man页面也说同样 -

此外,套接字API提供数据类型struct sockaddr_storage.此类型适用于容纳所有受支持的特定于域的套接字地址结构; 它足够大并且正确对齐.(特别是,它足以容纳IPv6套接字地址.)


我已经使用这两种类型转换看到多种实现CC++语言在野外,现在我不确定的事实,哪一个是正确的,因为有一些帖子说上述的权利要求相矛盾- 这个这个.

那么哪一个是填充sockaddr_storage结构的安全和正确的方法?这些指针转换是否安全?还是工会方法?我也知道这个getaddrinfo()电话,但对于刚刚填充结构的上述任务来说,这似乎有点复杂.memcpy还有另外一种推荐的方法,这样安全吗?

c c++ sockets linux strict-aliasing

14
推荐指数
2
解决办法
3178
查看次数

C中的结构和铸造

我在想:

如果我有结构定义,例如,像这样:

struct Base {
  int foo;
};

struct Derived {
  int foo; // int foo is common for both definitions
  char *bar;
};
Run Code Online (Sandbox Code Playgroud)

我可以这样做吗?

void foobar(void *ptr) {
  ((struct Base *)ptr)->foo = 1;
}

struct Derived s;

foobar(&s);
Run Code Online (Sandbox Code Playgroud)

例如,当它的类型实际上时,将void指针强制转换Base *为访问它?fooDerived *

c struct pointers casting

10
推荐指数
2
解决办法
1411
查看次数