背后ç插座SOCKADDR和sockaddr_storage推理 [英] Reasoning behind C sockets sockaddr and sockaddr_storage

查看:134
本文介绍了背后ç插座SOCKADDR和sockaddr_storage推理的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在看的功能,如连接()用C套接字和通知的bind()的他们采取一个指针的sockaddr 结构。我一直在阅读,使您的应用程序自动对焦无关,它是使用 sockaddr_storage 结构的指针,并将其转换为的sockaddr 因为所有的额外空间指针有较大的地址。

I'm looking at functions such as connect() and bind() in C sockets and notice that they take a pointer to a sockaddr struct. I've been reading and to make your application AF-Independent, it is useful to use the sockaddr_storage struct pointer and cast it to a sockaddr pointer because of all the extra space it has for larger addresses.

我想知道是怎么样的功能连接()绑定()这要求一个的sockaddr 指针去从一个指向一个比它期待一个更大的结构的指针访问数据。当然,你传递给它的结构的大小,你所提供的,但什么是该函数用于获取IP地址断指针到已转换为结构*的sockaddr较大的结构的实际语法

What I am wondering is how functions like connect() and bind() that ask for a sockaddr pointer go about accessing the data from a pointer that points at a larger structure than the one it is expecting. Sure, you pass it the size of the structure you are providing it, but what is the actual syntax that the functions use to get the IP Address off the pointers to larger structures that you have cast to struct *sockaddr?

这可能是因为我来自OOP语言,但它似乎是那种一个黑客和有点凌乱。

It's probably because I come from OOP languages, but it seems like kind of a hack and a bit messy.

推荐答案

函数期望一个指向结构sockaddr 可能强制转换为你送他们的指针的sockaddr 当你给他们一个指向结构sockaddr_storage 。这样一来,他们访问它,仿佛它是一个结构sockaddr

Functions that expect a pointer to struct sockaddr probably typecast the pointer you send them to sockaddr when you send them a pointer to struct sockaddr_storage. In that way, they access it as if it was a struct sockaddr.

结构sockaddr_storage 的设计适合于既结构SOCKADDR_IN 结构体sockaddr_in6

您没有创建自己的结构sockaddr ,你通常创建一个结构SOCKADDR_IN 结构体sockaddr_in6 取决于你所使用的IP版本。为了避免试图知道你会使用什么IP版本,可以使用结构sockaddr_storage 可容纳两种。这将反过来通过的connect(),绑定()等函数类型强制转换为结构sockaddr 和访问的方式。

You don't create your own struct sockaddr, you usually create a struct sockaddr_in or a struct sockaddr_in6 depending on what IP version you're using. In order to avoid trying to know what IP version you will be using, you can use a struct sockaddr_storage which can hold either. This will in turn be typecasted to struct sockaddr by the connect(), bind(), etc functions and accessed that way.

您可以看到所有这些下面的结构(填充是特定的实现,为对齐的目的):

You can see all of these structs below (the padding is implementation specific, for alignment purposes):

struct sockaddr {
   unsigned short    sa_family;    // address family, AF_xxx
   char              sa_data[14];  // 14 bytes of protocol address
};


struct sockaddr_in {
    short            sin_family;   // e.g. AF_INET, AF_INET6
    unsigned short   sin_port;     // e.g. htons(3490)
    struct in_addr   sin_addr;     // see struct in_addr, below
    char             sin_zero[8];  // zero this if you want to
};


struct sockaddr_in6 {
    u_int16_t       sin6_family;   // address family, AF_INET6
    u_int16_t       sin6_port;     // port number, Network Byte Order
    u_int32_t       sin6_flowinfo; // IPv6 flow information
    struct in6_addr sin6_addr;     // IPv6 address
    u_int32_t       sin6_scope_id; // Scope ID
};

struct sockaddr_storage {
    sa_family_t  ss_family;     // address family

    // all this is padding, implementation specific, ignore it:
    char      __ss_pad1[_SS_PAD1SIZE];
    int64_t   __ss_align;
    char      __ss_pad2[_SS_PAD2SIZE];
};

因此​​,大家可以看到,如果函数需要一个IPv4地址,它只会读取前4个字节(因为它假定结构是类型结构sockaddr 的。否则,它会读取对IPv6的完整的16个字节)。

So as you can see, if the function expects an IPv4 address, it will just read the first 4 bytes (because it assumes the struct is of type struct sockaddr. Otherwise it will read the full 16 bytes for IPv6).

这篇关于背后ç插座SOCKADDR和sockaddr_storage推理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆