Chinaunix首页 | 论坛 | 博客
  • 博客访问: 313674
  • 博文数量: 66
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 509
  • 用 户 组: 普通用户
  • 注册时间: 2015-04-29 13:56
文章分类
文章存档

2018年(2)

2017年(6)

2016年(34)

2015年(24)

我的朋友

分类: LINUX

2015-09-17 13:29:59

我们知道网络地址结构体 struct sockaddr 与 struct sockaddr_in 他们都表示网络地址,那么它们是什么关系呢?我们编程是该如何使用他们呢?什么时候该使用哪一个呢?

struct sockaddr 定义在/usr/include/bits/socket.h
  1. /* Get the definition of the macro to define the common sockaddr members. */
  2. #include <bits/sockaddr.h>

  3. /* Structure describing a generic socket address. */
  4. struct sockaddr
  5. {
  6.     __SOCKADDR_COMMON (sa_); /* Common data: address family and length. */
  7.     char sa_data[14];        /* Address data. */
  8. };
__SOCKADDR_COMMON 的定义在bits/sockaddr.h中:
  1. /*
  2.  * Never include this file directly; use <sys/socket.h> instead.
  3.  */
  4. #ifndef _BITS_SOCKADDR_H
  5. #define _BITS_SOCKADDR_H 1

  6. /* POSIX.1g specifies this type name for the `sa_family' member. */
  7. typedef unsigned short int sa_family_t;

  8. /* This macro is used to declare the initial common members
  9.    of the data types used for socket addresses, `struct sockaddr',
  10.    `struct sockaddr_in', `struct sockaddr_un', etc. */

  11. #define __SOCKADDR_COMMON(sa_prefix) \
  12.   sa_family_t sa_prefix##family

  13. #define __SOCKADDR_COMMON_SIZE (sizeof (unsigned short int))

  14. #endif /* bits/sockaddr.h */
    1. /* Structure describing a generic socket address. */
    2. struct sockaddr
    3. {
    4.     sa_family_t sa_family; /* address family */
    5.     char sa_data[14];      /* Address data. */
    6. };
    7. typedef unsigned short int sa_family_t;
根据注释,struct sockaddr是一个通用(generic)的socket地址。

struct sockaddr_in结构体定义在/usr/include/netinet/in.h中:
  1. /* Structure describing an Internet socket address. */
  2. struct sockaddr_in
  3. {
  4.     __SOCKADDR_COMMON (sin_);
  5.     in_port_t sin_port; /* Port number. */
  6.     struct in_addr sin_addr; /* Internet address. */

  7.     /* Pad to size of `struct sockaddr'. */
  8.     unsigned char sin_zero[sizeof (struct sockaddr) -
  9.                            __SOCKADDR_COMMON_SIZE -
  10.                            sizeof (in_port_t) -
  11.                            sizeof (struct in_addr)];
  12. };
将宏展开为:
  1. /* Structure describing an Internet socket address. */
  2. struct sockaddr_in
  3. {
  4.     sa_family_t sin_family;        /* address family */
  5.     in_port_t   sin_port;          /* Port number. */
  6.     struct in_addr sin_addr;       /* Internet address. */

  7.     /* Pad to size of `struct sockaddr'. */
  8.     unsigned char sin_zero[sizeof (struct sockaddr) -
  9.                            __SOCKADDR_COMMON_SIZE -
  10.                            sizeof (in_port_t) -
  11.                            sizeof (struct in_addr)];
  12. };

  13. /* Internet address. */
  14. typedef uint32_t in_addr_t;
  15. struct in_addr
  16. {
  17.     in_addr_t s_addr;
  18. };
根据注释,struct sockaddr_in 是一个Internate网socket地址。即一个TCP的socket地址。
显然结构体最后定义的sin_zero是为了补齐结构体,是它和struct sockaddr一样大。保持一样的大小,是为了他们之间的相互转换,因为下面的这些函数的地址参数都是struct sockaddr*

int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
                      const struct sockaddr *dest_addr, socklen_t addrlen);
                             
我们在TCP协议编程时,显然使用的是struct sockaddr_in地址,要使用这些函数,必须将struct sockaddr_in转换成struct sockaddr。所以才将两种的大小定义成一样大。

所以:
struct sockaddr是通用的套接字地址,而struct sockaddr_in则是internet环境下套接字的地址形式,二者长度一样,都是16个字节。二者是并列结构,指向sockaddr_in结构的指针也可以指向sockaddr。一般情况下,需要把sockaddr_in结构强制转换成sockaddr结构再传入系统调用函数中

我们还可以看大struct sockaddr_un,该结构体用于UNIX套接字。
阅读(1167) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~