具体请参见点击打开链接(https://github.com/uttp/UNIX-Network-Programming/blob/master/chapter3)
从第二部分基本套接字编程开始
第三章主要是套接字编程的简介,主要介绍了套接字编程后面要用到的主要函数
3.2节套接字地址结构
3.2.1 IPv4
套接字地址结构包含在头文件<netinet/in.h>中
struct in_addr
{
in_addr_t s_addr;
};
在其中in_addr_t一般为uint32_t(位整数,包含在头文件<sys/types.h>中)包含在头文件<netinet/in.h>中
struct scokaddr_in
{
uint8_t sin_len; /*结构体的长度*/
sa_family_t sin_family; /*AF_INET*/
in_port sin_port; /*16-bit的tcp或者udp的端口号*/
struct in_addr sin_addr; /*32位ipc4地址*/
char sin_zero[8]; /*保留未用*/
};
数据类型简要说明如下表
+--------------+-------------------------+---------------+
| 数据类型 | 说明 | 头文件 |
+--------------+-------------------------+---------------+
| int8_t | 带符号的8位整数 | <sys/types.h> |
| uint8_t | 无符号的8位整数 | <sys/types.h> |
| int16_t | 带符号的16位整数 | <sys/types.h> |
| uint16_t | 无符号的16位整数 | <sys/types.h> |
| int32_t | 带符号的32位整数 | <sys/types.h> |
| uint32_t | 无符号的32位整数 | <sys/types.h> |
+--------------+-------------------------+---------------+
| sa_family_t | 套接字地址结构地址族 | <sys/socket.h>|
| socketlen_t | 套接字地址结构长度 | <sys/socket.h>|
+--------------+-------------------------+---------------+
| in_addr_t | IPV4地址,一般为32位 | <netinet/in.h>|
| in_port_t | TCP或者UDP端口 | <netinet/in.h>|
+--------------+-------------------------+---------------+
3.2.2通用套接字地址结构
当作通用套接字地址结构作为一个参数传递进任何套接字函数时,它总是以引用的形式来传递。这样以指针作为参数来传递的任何套接字函数必须处理来所
支持的任何协议族的套接字地址结构。
因此出现了定义通用的套接字地址结构,申明在头文件<sys/socket.h>中
struct sockaddr
{
uint8_t sa_len; /*结构体长度*/
sa_family_t sa_family; /*AF_INT*/
char sa_data /*协议地址*/
};
因此都需要进行强制转化为通用套接字地址结构
eg. 函数 int bind(int,struct sockaddr *, socklen_t);
当函数地址结构为
struct sockaddr_in serv;时就要进行如下的强制类型转化
bind(sockfd,(struct sockaddr *) &serv, sizeof(serv));
3.2.3IPv6套接字地址结构
IPv6套接字地址结构在头文件<netinet/in.h>中定义,定义结构如下
struct in6_addr
{
uint8_t s6_addr[16];
};
struct sockaddr_in6
{
uint8_t sin6_len; /*结构体的长度*/
sa_family_t sin6_family /*AF_INET6*/
in_port_t sin6_port
uint32_t sin6_flowinfo;
struct in6_addr sin6_addr;
uint32_t sin6_scope_id;
};
3.2.4新的通用套接字地址结构
struct sockaddr_storage
{
uint8_t ss_len;
sa_family_t ss_family;
/*用户透明部分*/
}
3.2.5套接字地址结构比较
IPv4 IPv6
sockaddr_in{} sockaddr_in6
+-----+--------+ +----+--------+
| 长度|AF_INET | |长度|AF_INT6 |
+-----+--------+ +----+--------+
| 16位端口号 | |16位端口号 |
+--------------+ +-------------+
| 32位IPv4地址 | |32位流标 |
+--------------+ +-------------+
| 未用 | |128位IPv6地址|
+--------------+ +-------------+
固定长度(16个字节) |32位范围ID |
+-------------+
固定长度(28个字节)
3.3值-结果参数
套接字地址结构的传递方式有:从进程到内核和从内核到进程两种方式
(1)从进程到内核传递套接字地址结构的函数有3个:bind、connect、和sendto。
eg.struct sockaddr_in serv
connect(sockfd, (struct sockaddr*) &serv, sizeof(serv));
用户进程
+------------------------------------+
| int |
| +----+ +--------------+ |
| |长度| |套接字地址结构| |
| +-+--+ +-------+------+ |
| | | |
| 值 | | |
| | | |
| | | |
| | | |
| | |协议地址 |
+--------+----+------------+---------+
| |
+--------+-----------------+---------+
| | | |
| |
| |
| 内核 |
+------------------------------------+
(2)从内核到进程传递套接字地址结构的函数有4个:accept recvfrom getsockname和getpeername