2024-10-27 09:23:50 +00:00

111 lines
3.2 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

```cpp
#include <iostream>
#include <cstring>
#include <unistd.h>
#include <netdb.h>
#include <cstdlib>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
```
# 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);
```