scoket通信 -- 重要的sockaddr

sockaddr介绍

sockaddr是存储socket结构信息的结构体,它具有通用性。
在这里插入图片描述
sockaddr在后来ipv4出现之后进化成了sockaddr_in,其在结构体上已与sockaddr不同,而在ipv4用完之后,ipv6出现并产生了ipv6的衍生版本sockaddr_in6。然而为了兼容性,我们无论在使用ipv4还是ipv6进行通信时,都要将结构体强转为sockaddr类型,详见如下。

sockaddr

在这里插入图片描述

sockaddr_in – ipv4

在这里插入图片描述
在这里插入图片描述
需要注意的是结构体in_addr的结构
在这里插入图片描述

sockaddr_in6 – ipv6

在这里插入图片描述
在这里插入图片描述

sockaddr使用

这个sockaddr数据结构在服务端bind时,accept时,客户端connect时都有用,而且使用它的时候也比较不一样。

仅有的accept

extern int accept (int __fd, __SOCKADDR_ARG __addr,
		   socklen_t *__restrict __addr_len);

在连接过程中需要用到三个sockaddr_in,而仅有accept()函数的第二个参数__SOCKADDR_ARG __addr参数是传出参数,socklen_t *__restrict __addr_len是传入传出参数。

sockaddr定义 – ipv4为例

struct sockaddr_in serv_addr;

作为函数参数

struct sockaddr_in listen_addr; 
listen_addr.sin_family = AF_INET;
listen_addr.sin_port = htons(PORT);
listen_addr.sin_addr.s_addr = htonl(INADDR_ANY);
bind(sockfd, (struct sockaddr *) &serv_addr, 
sizeof(serv_addr))
//由于client_len是一个传入传出参数,必须有初始值
int client_len = sizeof(accept_addr);	
int accept_fd = accept(listen_fd, (struct sockaddr *)&accept_addr, &client_len)
accept返回的accept_fd 包含了客户端的ip和port信息
//但是需要注意的是这些信息都是以网络字节序的形式传输过来的,需要进行转换
accept_addr.sin_addr.s_addr
accept_addr.sin_port)
struct sockaddr_in connect_addr;
inet_pton(AF_INET,"127.0.0.1",&connect_addr.sin_addr.s_addr);
connect_addr.sin_family = AF_INET;
connect_addr.sin_port = htons(PORT);
connect(sockfd, (struct sockaddr *) &serv_addr,
sizeof(serv_addr))

那之所以要将sockaddr_in 强转为sockaddr原因之一是为了兼容ipv6,当然ipv6也同样需要强转,互相兼容。

sockaddr成员初始化

服务端

bind()

服务端在bind时,必须给sockaddr_in的成员赋值

 serv_addr.sin_family = AF_INET;
 serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);	
 //服务端不需要ip地址,INADDR_ANY可以自动取出系统有效的任意ip,取出来默认是int型
serv_addr.sin_port = htons(PORT);

accept()

accept不需要初始化,因为它是用来接收connect的信息的 ,但是一定要复制。

客户端

客户端在connect时,也必须给sockaddr_in的成员赋值,规定连接的协议族和服务端ip与port,否则就不能能连接上服务端,这是显而易见的。

client_sockaddr.sin_port = htons(port); 
// 设置端口号
client_sockaddr.sin_family = AF_INET; 
// 设置地址族为IPv4
client_sockaddr.sin_addr.s_addr = inet_addr(ip_str); 
// 设置IP地址

注:关于sockaddr这个结构体还有什么需要注意的点我也不清楚,就比如下面这个

__SOCKADDR_COMMON (sa_);	/* Common data: address family and length.  */

/* 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
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值