我们知道网络地址结构体 struct sockaddr 与 struct sockaddr_in 他们都表示网络地址,那么它们是什么关系呢?我们编程是该如何使用他们呢?什么时候该使用哪一个呢?
struct sockaddr 定义在/usr/include/bits/socket.h
- /* Get the definition of the macro to define the common sockaddr members. */
-
#include <bits/sockaddr.h>
-
-
/* Structure describing a generic socket address. */
-
struct sockaddr
- {
-
__SOCKADDR_COMMON (sa_); /* Common data: address family and length. */
-
char sa_data[14]; /* Address data. */
- };
宏 __SOCKADDR_COMMON 的定义在bits/sockaddr.h中:
- /*
-
* Never include this file directly; use <sys/socket.h> instead.
-
*/
-
#ifndef _BITS_SOCKADDR_H
-
#define _BITS_SOCKADDR_H 1
-
-
/* POSIX.1g specifies this type name for the `sa_family' member. */
-
typedef unsigned short int sa_family_t;
-
-
/* This macro is used to declare the initial common members
-
of the data types used for socket addresses, `struct sockaddr',
-
`struct sockaddr_in', `struct sockaddr_un', etc. */
-
-
#define __SOCKADDR_COMMON(sa_prefix) \
-
sa_family_t sa_prefix##family
-
-
#define __SOCKADDR_COMMON_SIZE (sizeof (unsigned short int))
-
-
#endif /* bits/sockaddr.h */
- /* Structure describing a generic socket address. */
-
struct sockaddr
-
{
-
sa_family_t sa_family; /* address family */
-
char sa_data[14]; /* Address data. */
-
};
- typedef unsigned short int sa_family_t;
根据注释,struct sockaddr是一个通用(generic)的socket地址。
struct sockaddr_in结构体定义在/usr/include/netinet/in.h中:
- /* Structure describing an Internet socket address. */
-
struct sockaddr_in
- {
-
__SOCKADDR_COMMON (sin_);
-
in_port_t sin_port; /* Port number. */
-
struct in_addr sin_addr; /* Internet address. */
-
-
/* Pad to size of `struct sockaddr'. */
-
unsigned char sin_zero[sizeof (struct sockaddr) -
-
__SOCKADDR_COMMON_SIZE -
-
sizeof (in_port_t) -
-
sizeof (struct in_addr)];
- };
将宏展开为:
- /* Structure describing an Internet socket address. */
-
struct sockaddr_in
-
{
-
sa_family_t sin_family; /* address family */
-
in_port_t sin_port; /* Port number. */
-
struct in_addr sin_addr; /* Internet address. */
-
-
/* Pad to size of `struct sockaddr'. */
-
unsigned char sin_zero[sizeof (struct sockaddr) -
-
__SOCKADDR_COMMON_SIZE -
-
sizeof (in_port_t) -
-
sizeof (struct in_addr)];
-
};
-
-
/* Internet address. */
-
typedef uint32_t in_addr_t;
-
struct in_addr
-
{
-
in_addr_t s_addr;
-
};
根据注释,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套接字。
阅读(490) | 评论(0) | 转发(0) |