网络基础知识
网络分层
- 每一层实现不同的功能,对上层的数据做透明传输
- 每一层向上层提供服务,同时使用下层提供的服务
各层典型的协议:
- 网络接口与物理层:
- MAC地址: 48位全球唯一,网络设备的身份标识
- ARP/RARP:
- ARP: IP地址——->MAC地址
- RARP: MAC地址—->IP地址
- PPP协议: 拨号协议(GPRS/3G/4G)
- 网络层:
- IP: Internet protocol(分为IPV4和IPV6)
- ICMP: Internet控制管理协议,ping命令属于ICMP
- IGMP: Internet分组管理协议,广播、组播
- 传输层:
- TCP: (Transfer Control protocol,传输控制协议) 提供面向连接的,一对一的可靠数据传输的协议
即数据无误、数据无丢失、数据无失序、数据无重复到达的通信 - UDP: (user Datagram Protocol, 用户数据报协议): 提供不可靠,无连接的尽力传输协议
是不可靠的无连接的协议。在数据发送前,因为不需要进行连接,所以可以进行高效率的数据传输 - SCTP: 是可靠传输,是TCP的增强版,它能实现多主机、多链路的通信
- TCP: (Transfer Control protocol,传输控制协议) 提供面向连接的,一对一的可靠数据传输的协议
- 应用层:
- 网页访问协议:HTTP/HTTPS
- 邮件发送接收协议: POP3(收)/SMTP(发) 、IMAP(可接收邮件的一部分)
- FTP
- Telnet/SSH: 远程登录
- NTP: 网络时钟协议
- SNMP: 简单网络管理协议(实现对网络设备集中式管理)
- RTP/RTSP:用传输音视频的协议(安防监控)
下图为TCP/IP协议通信模型
网络的封包和拆包
网络编程基础知识
SOCKET
- socket是一个应用编程的接口,它是一种特殊的文件描述符(对它执行IO的操作函数,比如,
read()
,write()
,close()
等操作函数){% p red::注意没有open函数%} - socket代表着网络编程的一种资源
- socket的类型:
IP
- IP地址分为IPV4和IPV6
- IPV4:采用32位的整数来表示
- IPV6:采用了128位整数来表示
- IPV4地址:
- 点分形式: 192.168.7.246
- 32位整数(4字节)
- 特殊IP地址:
- 局域网IP: 192.XXX.XXX.XXX 10.XXX.XXX.XXX
- 广播IP: xxx.xxx.xxx.255, 255.255.255.255(全网广播)
- 组播IP: 224.XXX.XXX.XXX~239.xxx.xxx.xxx
端口
端口号一般由IANA (Internet Assigned Numbers Authority) 管理
端口号是一个16位的数字(1-65535)
- 众所周知端口: 1~1023(FTP: 21,SSH: 22, HTTP:80, HTTPS:469)
- 保留端口: 1024-5000(不建议使用)
- 可以使用的:5000~65535
TCP端口和UDP端口是相互独立的,网络里面的通信是由 IP地址+端口号 来决定
字节序
字节序是指不同的CPU访问内存中的多字节数据时候,存在大小端问题。
大端模式,是指数据的高字节保存在内存的低地址中,而数据的低字节保存在内存的高地址中,这样的存储模式有点儿类似于把数据当作字符串顺序处理:地址由小向大增加,而数据从高位往低位放;
小端模式,是指数据的高字节保存在内存的高地址中,而数据的低字节保存在内存的低地址中,这种存储模式将地址的高低和数据位权有效地结合起来,高地址部分权值高,低地址部分权值低,和我们的逻辑方法一致。
一般来说:
- X86/ARM: 小端
- powerpc/mips, ARM作为路由器时,大端模式
- 网络传输的时候采用大端模式
主机字节序与网络字节序转化:
ip地址转化
in_addr_t inet_addr(const char *cp);
特点:
- 仅适应于IPV4
- 此函数不能用于255.255.255.255的转换
参数:
cp
: 点分形式的IP地址,结果是32位整数(内部包含了字节序的转换,默认是网络字节序的模式)
返回值:
- 成功:返回转化后的IP地址
- 失败:返回-1
inet_pton()
inet_ntop()
特点:
- 适应于IPV4和IPV6
- 能正确的处理255.255.255.255的转换问题
参数:
af
: 地址协议族(AF_INET或AF_INET6)src
:是一个指针(填写点分形式的IP地址[主要指IPV4])dst
: 转换的结果给到dst
返回值:
- 成功:返回1
- 失败:如果
src
的格式错误,则返回0 - 失败:如果
af
格式错误,则返回-1
TCP编程API
socket()函数
参数:
domain
:- AF_INET IPv4 Internet protocols
- AF_INET6 IPv6 Internet protocols
- AF_UNIX, AF_LOCAL Local communication
- AF_NETLINK Kernel user interface device
- AF_PACKET Low level packet interface
type
- SOCK_STREAM 流式套接字 唯一对应于TCP
- SOCK_DGRAM 数据报套接字,唯一对应着UDP
- SOCK_RAW 原始套接字
protocol
: 一般填0,原始套接字编程时需填充
返回值:
成功时返回文件描述符,出错时返回为-1
bind()函数
参数:
sockfd
: 通过socket()
函数拿到的fdaddr
:struct sockaddr
的结构体变量的地址addrlen
: 地址长度
通用地址结构体:
struct sockaddr
{
u_short sa_family; // 地址族, AF_xxx
char sa_data[14]; // 14字节协议地址
};
Internet协议地址结构:
struct sockaddr_in
{
u_short sin_family; // 地址族, AF_INET,2 bytes
u_short sin_port; // 端口,2 bytes
struct in_addr sin_addr; // IPV4地址,4 bytes
char sin_zero[8]; // 8 bytes unused,作为填充
};
IPv4地址结构:
struct in_addr
{
in_addr_t s_addr; // u32 network address
};
实际开发的时候,通过把sockaddr_in
结构体强制转化成sockaddr
结构体后,作为参数传入bind()
函数。
实例:
如果是IPV6的编程,要使用struct sockddr_in6
结构体(详细情况请参考man 7 ipv6),通常更通用的方法可以通过struct sockaddr_storage
来编程。
listen()
把主动套接字变成被动套接字。
参数:
sockfd
: 通过socket()
函数拿到的fdbacklog
: 同时允许几路客户端和服务器进行正在连接的过程(正在三次握手)
一般填5, 测试得知,ARM最大为8
比如:listen(fd, 5)
表示系统允许11(=2*5+1)个客户端同时进行三次握手
返回值:
- 成功:返回0
- 失败:返回-1
accept()
阻塞等待客户端连接请求 。
参数:
sockfd
: 经过前面socket()
创建并通过bind()
,listen()
设置过的fdaddr
和addrlen
: 获取连接过来的客户的信息
返回值:
- 成功:返回已经建立好连接的新的newfd
- 失败:返回-1
connect()
客户端的连接函数。
connect()
函数和服务器的bind()
函数写法类似:
参数:
sockfd
: 通过socket()函数拿到的fdaddr
:struct sockaddr
的结构体变量的地址addrlen
: 地址长度
返回值:
- 成功:返回0
- 失败:返回-1