# net ```cpp #include #include #include #include #include #include #include #include ``` # tips + 所有网络函数失败基本是返回 -1,errno被设置 # socket 原型: int socket(int domain, int type, int protocol) + domain 协议族 \ PF_INET # IPv4 互联网协议族 \ PF_INET6 # IPv6 互联网协议族 \ PF_LOCAL # 本地通讯地址族 + type 数据传输类型 \ SOCK_STREAM # 面向连接; 数据不丢失; 数据顺序不错乱; 双向通道; \ SOCK_DGRAM # 无连接; 数据可能丢; 数据可能错乱; 效率高; + protocol 最终使用协议 \ IPPROTO_TCP \ IPPROTO_UDP \ 0 # 编译器自动识别 # 主机字节序和网络字节序 + 大端序和小端序 (如果数据大于1B,CPU在内存中存放数据的方式) \ 大端序 低位字节在高位,高位字节在低位 \ 小端序 低位字节在低位,高位字节在高位 (INTEL) ## 字节序不同的系统字节传输数据,可能会出现问题,所以网络字节序约定使用大端序 + c提供了4个库用于主机字节序和网络字节序之间的转换 \ uint16_t htons(uint16_t hostshort); // 2字节的整数 \ uint32_t htonl(uint32_t hostshort); // 4字节的整数 \ uint16_t ntons(uint16_t netshort); // 2字节的整数 \ uint32_t ntonl(uint32_t netshort); // 4字节的整数 // h host主机 // to 转换 // n network网络 // s short(2byte) // l long(4byte) # IP地址和通讯端口 + IPv4(4byte) 端口(2byte) # 大小端序的处理 + 在网络编程中数据收发有自动转换,只有sockaddr_in结构成员变量填充数据时,才需要考虑字节序 # 结构体 ## sockaddr ```cpp struct sockaddr { // connect() bind() 都需要 unsigned short sa_family; // 协议族 unsigned char sa_data[14]; // 14byte的端口和地址 } ``` ## sockaddr_in ```cpp struct sockaddr { // 为了方便操作,大小与sockaddr相同,可以强制转换 unsigned short sin_family; // 协议族 unsigned short sin_port; // 2byte端口号 //struct in_addr sin_addr; // 4byte地址 unsigned int sin_addr; // 4byte地址 unsigned char sin_zero[8]; // 保留,长度对齐 } ``` # gethostbyname函数 + 用 域名/主机名/字符串IP 转换成大端序 ```cpp struct hostent *gethostbyname(const char *name); struct hostent { char *h_name; // 主机名 char **h_aliases; // 主机所有别名的字符串数组 short h_addrtype; // 主机IP类型,IPv4或IPv6 short h_length; // 主机IP长度 char **h_addr_list; // 主机IP地址,以网络字节序存储 } #define h_addr h_addr_list[0] // 转换后,用 memcpy(&servaddr.sin_addr, h->h_addr, h->h_length); ``` # 字符串IP和大端序IP的转换 ## atoi() 把字符串IP转换成大端序 ```cpp typedef unsigned int in_addr_t; //4byte大端序IP // 字符串转大端序IP,转换后IP赋给sockaddr_in.in_addr.s_addr in_addr_t inet_addr(const char *cp); // 字符串转大端序IP,转换后IP赋给sockaddr_in.in_addr int inet_aton(const char *cp, struct in_addr *inp); //大转字符串,用于服务端解析IP char *inet_ntoa(struct in_addr in); ```