-
/***********ipv4的套接字地址*********************************/
-
-
struct sockaddr_in {
-
__kernel_sa_family_t sin_family; /* AF_INET */
-
__be16 sin_port; /* Port number */
-
struct in_addr sin_addr; /* Internet address */
-
-
/* Pad to size of `struct sockaddr'. */
-
unsigned char __pad[__SOCK_SIZE__ - sizeof(short int) -
-
sizeof(unsigned short int) - sizeof(struct in_addr)];
-
};
-
/********* ipv6的套接字地址***********************/
-
-
struct sockaddr_in6 {
-
unsigned short int sin6_family; /* AF_INET6 */
-
__be16 sin6_port; /* Transport layer port # */
-
__be32 sin6_flowinfo; /* IPv6 flow information */
-
struct in6_addr sin6_addr; /* IPv6 address */
-
__u32 sin6_scope_id; /* scope id (new in RFC2553) */
-
};
-
/*********netlink通讯的套接字地址**************************/
-
struct sockaddr_nl {
-
__kernel_sa_family_t nl_family; /* AF_NETLINK */
-
unsigned short nl_pad; /* zero */
-
__u32 nl_pid; /* port ID */
-
__u32 nl_groups; /* multicast groups mask */
-
};
-
/*设备无关的物理层地址结构,通过setsockopt可以设置网卡的多播或混杂模*/
-
-
struct sockaddr_ll {
-
unsigned short sll_family; /* AF_PACKET*/
-
__be16 sll_protocol;
-
int sll_ifindex;
-
unsigned short sll_hatype;
-
unsigned char sll_pkttype;
-
unsigned char sll_halen;
-
unsigned char sll_addr[8];
-
};
-
linux 2.0 以前的版本是用struct
sockaddr_pkt 的,而且获取二层的socket是通过socket(AF_INET, SOCK_PACKET, protocol)来获取的,并没有AF_PACKET 这个domain ,只有SOCK_PACKET这个socket_type
-
/*********通用套接字地址**************************/
-
-
struct sockaddr {
-
sa_family_t sa_family; /* address family, AF_xxx */
-
char sa_data[14]; /* 14 bytes of protocol address */
-
};
-
-
-
#define _K_SS_MAXSIZE 128 /* Implementation specific max size */
-
#define _K_SS_ALIGNSIZE (__alignof__ (struct sockaddr *))
-
/* Implementation specific desired alignment */
-
-
typedef unsigned short __kernel_sa_family_t;
-
-
#define sockaddr_storage __kernel_sockaddr_storage
-
struct __kernel_sockaddr_storage {
-
__kernel_sa_family_t ss_family; /* address family */
-
/* Following field(s) are implementation specific */
-
char __data[_K_SS_MAXSIZE - sizeof(unsigned short)];
-
/* space to achieve desired size, */
-
/* _SS_MAXSIZE value minus size of ss_family */
-
} __attribute__ ((aligned(_K_SS_ALIGNSIZE))); /* force desired alignment */
-
-
struct sockaddr 和struct sockaddr_storage 都是通用套接字
为了统一各种协议,
socket对应的接口就定义了两个通用结构,分别是
sockaddr(16字节
)和
sockaddr_storage(128字节
) ,其中
sockaddr_storage是为了适配
sockaddr_in6(28字节
)这样长度比较大的协议而后来定义的,如果需要用到
sockaddr_storage 这样的通用套接字,则强转为
sockaddr,并且长度用
sizeof(struct sockaddr_storage)
网络编程中的一下几个接口会用到以上的数据结构
应用层->内核,对应用层来说就是发送的,数据是送到协议栈的,addrlen是入参
int bind
(int sockfd, struct sockaddr *my_addr, socklen_t addrlen);
int connect(int sockfd, const struct
sockaddr *serv_addr, socklen_t addrlen);
int sendto (int s, const void *msg, size_t
len, int flags, const struct sockaddr *to, socklen_t tolen);
内核->应用层的,对应用层来说就是接收的,数据从协议栈上来的,addrlen是值-结果参数
int
accept (int s, struct sockaddr
*addr, socklen_t *addrlen);
int recvfrom
(int s, void *buf, size_t len, int
flags, struct sockaddr *from, socklen_t *fromlen);
int
getpeername(int s, struct sockaddr *name, socklen_t *namelen);
int getsockname(int s, struct sockaddr *name,
socklen_t *namelen);
getsockname: 返回本地协议地址:getpeername:返回远程协议地址
适用场景:
1.当不用bind()或调用bind()没有指定本地协议地址时,可以调用getsockname()来返回内核分配给此连接的本地IP地址和端口号,还可以获得某套接口的协议族。
2.当一个新的连接建立时,服务器也可以调用getsockname()来获得分配给此连接的本地IP地址。
3.当一个服务器的子进程调用exec函数启动执行时,只能调用getpeername()函数来获得客户的Ip地址和端口号。
4.未调用bind()就调用了connect(),这时唯有getsockname()调用可以获知系统内定的本地地址。在返回时,namelen参数包含了名字的实际字节数。
阅读(21178) | 评论(0) | 转发(1) |