struct sockaddr
和struct sockaddr_un
有什么不同?
我知道我们在客户端服务器模块中使用这些结构体,将套接字绑定到套接字地址。而且我们使用强制类型转换操作符来接受“sockaddr_un
”结构体。
我想知道它们之间的区别/相似之处以及为什么需要强制类型转换操作符。
struct sockaddr
和struct sockaddr_un
有什么不同?
我知道我们在客户端服务器模块中使用这些结构体,将套接字绑定到套接字地址。而且我们使用强制类型转换操作符来接受“sockaddr_un
”结构体。
我想知道它们之间的区别/相似之处以及为什么需要强制类型转换操作符。
“struct sockaddr”是通用的定义。它被任何需要地址的套接字函数使用。
“struct sockaddr_un”(Unix套接字地址)是一种特定类型的地址族。
更常见的“struct sockaddr_in”(Internet套接字地址)是另一种特定类型的地址族。
强制转换是使套接字API接受常规参数类型,该类型实际上可以是几种不同的实际类型之一所必需的。
这是一个很好的链接,显示了几个不同的地址族定义:
http://www.cas.mcmaster.ca/~qiao/courses/cs3mh3/tutorials/socket.html
"struct sockaddr
通常只应该用作指针的基础类型。它是一个结构体,旨在覆盖特定地址族的套接字地址类型(例如struct sockaddr_un
、struct sockaddr_in
、struct sockaddr_in6
等)中成员的通用初始顺序。
你唯一可以依赖struct sockaddr
的成员是一个单独的sa_family_t
,表示套接字地址族。这个想法是为了获得一种类似于多态的效果-可以有一个函数可以操作几种不同的套接字地址类型:
void foo(struct sockaddr *sa)
{
switch(sa->sa_family)
{
case AF_INET: {
struct sockaddr_in *sa_in = (struct sockaddr_in *)sa;
/* AF_INET processing */
}
case AF_UNIX: {
struct sockaddr_un *sa_un = (struct sockaddr_un *)sa;
/* AF_UNIX processing */
}
/* ... */
需要注意的是,像上面那样的代码通常被认为违反了C语言中的“严格别名规则” - 如果你想在自己的代码中这样做,应该使用联合类型:
union sockaddr {
struct sockaddr sa;
struct sockaddr_in sin;
struct sockaddr_un sun;
/* ... */
};
void foo(union sockaddr *sa_union)
{
struct sockaddr *sa = (struct sockaddr *)sa_union;
switch(sa->sa_family)
{
case AF_INET: {
struct sockaddr_in *sa_in = (struct sockaddr_in *)sa;
/* AF_INET processing */
}
case AF_UNIX: {
struct sockaddr_un *sa_un = (struct sockaddr_un *)sa;
/* AF_UNIX processing */
}
/* ... */