结构体
各类结构体以不同方式存放不同类型、不同数量的Socket信息,作为不同Socket接口函数的输入参数使用
in_addr
表示32位的IPv4地址
1 2 3 4 5 6 7 8 9
| #include <arpa/inet.h>
struct in_addr{ in_addr_t s_addr; }
|
sockaddr
套接字结构
1 2 3 4 5 6 7 8 9
| #include <sys/socket.h>
struct sockaddr{ sa_family_t sin_family; char sa_data[14]; }
|
sockaddr_in
套接字结构
1 2 3 4 5 6 7 8 9 10
| #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h>
struct sockaddr_in{ sa_family_t sin_family; unsigned short sin_port; struct in_addr sin_addr; char sin_zero[8]; }
|
函数
字节序转换
字节序指在内存中存放大于一个字节的数据时,数据各字节的存放顺序。
字节序可分为:
大端字节序:高位字节在前,低位字节在后
小端字节序:低位字节在前,高位字节在后
设计两种字节序的原因:
大端字节序符合人类的读写习惯,比如我们想存放“一千二百三十四”这个十进制数字(转换为十六进制为0x04D2),用大端字节序存储后,当我们读取时还是0x04D2。
但如果用小端字节序存储,读取时就变为0xD204。虽然小端字节序不符合人类读写习惯,但有利于提高计算效率,因为计算机计算时都是从数据的低位开始计算。
主机字节序:小端字节序
网络字节序:大端字节序
普通数据的字节序转换
主机字节序—>网络字节序
功能:无符号32位/16位整型数据转换
参数:主机字节序数据
返回值:网络字节序数据
1 2 3 4
| #include <arpa/inet.h>
uint32_t htonl(uint32_t hostlong); uint16_t htons(uint16_t hostshort);
|
网络字节序—>主机字节序
功能:无符号32位/16位整型数据转换
参数:网络字节序数据
返回值:主机字节序数据
1 2 3 4
| #include <arpa/inet.h>
uint32_t ntohl(uint32_t netlong); uint16_t ntohs(uint16_t netshort);
|
IP地址的字节序转换
字符串—>网络字节序
inet_pton
参数af:地址协议族(AF_INET、AF_INET6)
参数strptr:指向IP字符串存储地址的指针
参数addrptr:指向网络字节序IP数据存储地址的指针
返回值:成功返回1,输入的IP地址无效返回0,出错返回-1
1 2 3
| #include <arpa/inet.h>
int inet_pton(int af, const char *strptr, void *addrptr);
|
inet_aton
参数cp:指向IP字符串存储地址的指针
参数inp:指向in_addr结构体的指针,结构体内s_addr存储转换后的格式为网络字节序的32位二进制格式的IP
返回值:成功返回非0,IP地址无效返回0
1 2 3
| #include <arpa/inet.h>
int inet_aton(const char *cp, struct in_addr *inp);
|
inet_addr
参数cp:指向IP字符串存储地址的指针
返回值:in_addr_t类型变量,存储网络字节序的32位二进制格式的IP
1 2 3
| #include <arpa/inet.h>
in_addr_t inet_addr(const char *cp);
|
字符串—>主机字节序
inet_network
参数cp:指向IP字符串存储地址的指针
返回值:in_addr_t类型变量,存储主机字节序的32位二进制格式的IP
1 2 3
| #include <arpa/inet.h>
in_addr_t inet_network(const char *cp);
|
网络字节序—>字符串
inet_ntop
参数af:地址协议族
参数addrptr:指向网络字节序IP数据存储地址的指针
参数strptr:指向IP字符串存储地址的指针
参数len:IP字符串存储地址空间大小
返回值:成功返回参数strptr的指针,失败返回NULL且修改errno的值。
1 2 3
| #include <arpa/inet.h>
const char *inet_ntop(int af, const void *addrptr, char *strptr, size_t len);
|
inet_ntoa
参数in:in_addr结构体,结构体内s_addr存储网络字节序的32位二进制格式的IP
返回值:指向IP字符串存储地址的指针
1 2 3
| #include <arpa/inet.h>
char *inet_ntoa(struct in_addr in);
|
测试
测试inet_pton、inet_ntop
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| #include <stdio.h> #include <arpa/inet.h> #include <string.h>
int main(){ char ip_str[] ="193.168.1.10"; in_addr_t ip_addr; int re = inet_pton(AF_INET, ip_str, (void *)&ip_addr); printf("inet_pton返回值 = %d\n",re); printf("ip_addr = %d\n",ip_addr); printf("-------\n"); char ip_str2[INET_ADDRSTRLEN]; const char *re2 = inet_ntop(AF_INET, (const void *)&ip_addr, ip_str2, sizeof(ip_str2)); printf("inet_ntop返回值 = %s\n", re2); printf("ip_str2 = %s\n",ip_str2); }
|
测试inet_aton、inet_ntoa
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| #include <stdio.h> #include <arpa/inet.h> #include <string.h>
int main(){ char ip_str[] ="193.168.1.10"; struct in_addr ip_addr; int re = inet_aton(ip_str, &ip_addr); printf("inet_aton返回值 = %d\n",re); printf("ip_addr.s_addr = %d\n",ip_addr.s_addr); printf("-------\n"); char *ip_str2; ip_str2 = inet_ntoa(ip_addr); printf("inet_ntoa返回值 = %s\n", ip_str2); }
|
测试inet_addr、inet_network
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| #include <stdio.h> #include <arpa/inet.h> #include <string.h>
int main(){ char ip_str[] ="193.168.1.10"; struct in_addr ip_addr1; ip_addr1.s_addr = inet_addr(ip_str); printf("inet_addr返回值 = %u\n",ip_addr1.s_addr); printf("-------\n"); struct in_addr ip_addr2; ip_addr2.s_addr = inet_network(ip_str); printf("inet_network返回值 = %u\n", ip_addr2.s_addr); }
|
IP地址处理
IP地址—>主机地址
参数in:in_addr结构体
返回值:in_addr_t类型变量,存储主机字节序的主机地址数据
1 2 3 4 5
| #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h>
in_addr_t inet_lnaof(struct in_addr in);
|
IP地址—>网络地址
参数in:in_addr结构体
返回值:in_addr_t类型变量,存储主机字节序的网络地址数据
1 2 3 4 5
| #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h>
in_addr_t inet_netof(struct in_addr in);
|
主机地址+网络地址—>IP地址
参数net:in_addr_t类型变量,存储网络字节序的网络地址数据
参数host:in_addr_t类型变量,存储网络字节序的主机地址数据
返回值:in_addr结构体,内部包含in_addr_t类型变量,存储网络主机字节序的IP地址数据
1 2 3 4 5
| #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h>
struct in_addr inet_makeaddr(in_addr_t net, in_addr_t host);
|
测试
测试inet_lnaof、inet_netof、inet_makeaddr
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
| #include <stdio.h> #include <arpa/inet.h> #include <string.h>
int main(){ char ip_str1[] = "44.135.86.12"; char ip_str2[] = "172.16.23.95"; char *ip_str; char *net_str1; char *net_str2; char *host_str1; char *host_str2;
struct in_addr ip_addr1; struct in_addr ip_addr2; struct in_addr ip_addr; struct in_addr net_addr1; struct in_addr net_addr2; struct in_addr host_addr1; struct in_addr host_addr2; inet_aton(ip_str1,&ip_addr1); host_addr1.s_addr = inet_lnaof(ip_addr1); host_addr1.s_addr = htonl(host_addr1.s_addr); host_str1 = inet_ntoa(host_addr1); printf("主机地址:%s\n",host_str1); net_addr1.s_addr = inet_netof(ip_addr1); net_addr1.s_addr = htonl(net_addr1.s_addr); net_str1 = inet_ntoa(net_addr1); printf("网络地址:%s\n",net_str1); host_addr1.s_addr = ntohl(host_addr1.s_addr); net_addr1.s_addr = ntohl(net_addr1.s_addr); ip_addr = inet_makeaddr(net_addr1.s_addr, host_addr1.s_addr); ip_str = inet_ntoa(ip_addr); printf("IP地址:%s\n",ip_str);
inet_aton(ip_str2,&ip_addr2); host_addr2.s_addr = inet_lnaof(ip_addr2); host_addr2.s_addr = htonl(host_addr2.s_addr); host_str2 = inet_ntoa(host_addr2); printf("主机地址:%s\n",host_str2); net_addr2.s_addr = inet_netof(ip_addr2); net_addr2.s_addr = htonl(net_addr2.s_addr); net_str2 = inet_ntoa(net_addr2); printf("网络地址:%s\n",net_str2); }
|
常规SocketC
TCP
服务端
客户端
UDP
服务端
客户端