概述
复习笔记,应付秋招。
应用层
HTTP
HTTP是Web在应用层的主要协议,其使用TCP作为运输层协议。HTTP客户与服务端首先会建立一个TCP连接,双方通过TCP套接字进行通信。HTTP是一个无状态的协议,服务端不会记录用户的任何信息。
HTTP协议中处理连接的方式有两种:持续连接与非持续连接。前者建立一个较长时间的TCP连接,能处理多个请求-响应的过程;后者在处理每一个请求-响应过程都会开一个新的TCP连接,处理完后会关闭。两者的优劣很明显。由于TCP的建立与释放都需要一定的时间,非持续连接下频繁的建立/释放TCP,肯定会影响应用的通信性能;而在用户与连接数过多的情况下,持续连接可能会耗尽服务器的资源,同时持续连接的存活时间过长也会带来安全问题。
HTTP可以使用cookie来记录用户的状态,cookie是服务器发送给客户、由客户保存的一个文件,客户每次与服务器通信时都会带上这个cookie标识以表示自己。
DNS
网络上的主机都是使用IP地址来进行寻址的,但是IP地址不便于使用,因此一般使用主机名(hostname)来寻址。把主机名转换成IP地址就需要依赖DNS(Domain Name System),其运行在UDP协议之上。
运输层
TCP(Transmission Control Protocol)和UDP(User Datagram Protocol)都属于传输层的协议,前者面向连接,而后者面向无连接,两者互为补充。
TCP
连接
TCP的特点就在于它的可靠交付,面向连接意味着通信双方在传输数据前需要建立可靠连接。TCP的三次握手见下图(图源网络):
为什么是三次握手?为了防止已经失效的请求报文再次传到服务器导致连接。如果使用两次握手,假设第一次客服端的请求报文在网络中堵塞住了,然后又发送了一个请求报文,结果第二次的请求报文先到达服务器并且建立了连接。若通信结束后,第一次发送的请求报文到达了服务器,导致又一次建立了连接。使用三次握手就不会出现这样的问题,因为服务器收到请求报文后还需要客户端的确认。很久以前在网上看到一个比喻,TCP的三次握手相当于日常中的打电话,只有通过三次握手才能保证连接的可靠性。A打电话给B,首先要问“B听得到吗?”,询问A->B的连通性,这是第一次;然后B回应“我听得到,你听得到吗?”,确认A->B的连通性且询问B->A的联通性,这是第二次;最后A回应“听得到”,确认B->A的联通性,这是第三次,接着A就可以说话(传输数据)了。
TCP连接的断开需要四次挥手,主要是为了保证数据能够被完整传输。四次挥手见下图(图源网络):
- 当客服端不再需要发送数据时,给服务器发送释放请求;
- 服务器接收请求发送回应,表示收到释放请求,但是服务器可能还有数据没有发送完,若有数据还会继续发送数据;
- 服务发送完数据,然后在发送释放信号,表示数据发送完毕;
- 客户端接收发送完毕的信号,作出回应并关闭连接,服务器收到回应也会关闭连接。
可靠传输
- 回退N步(Go-Back-N):使用滑动窗口一次发送多个分组,根据确认结果移动窗口。
- 选择重传(Selecetive Repeat):发送发只需要重新发送那些窗口内未被确认的报文分组。
拥塞控制
- 慢启动:拥塞窗口的大小以指数形式增长,当遇到丢包时重置;
- 拥塞避免:当拥塞窗口到达一定值时,增长变缓;
- 快恢复(可选组件):当遇到丢包时,并不重置,而是设置为一半左右然后再增长。
UDP
如果把TCP比作打电话,那么UDP相当于发短信。UDP只保证尽力的交付,它只管发送,不管对方有没有收到甚至存不存在。当使用UDP作为传输层协议时,可靠性只能交给上层(应用层)协议来保证。
网络层
网络层的核心协议就是网际协议(Internet Protocol),IP协议数据报的重要字段有如下几个:
- 数据报长度:16bit,该字段限制了数据报的最大理论长度为$2^16$字节。
- TTL(Time To Tive):数据报每经过一台路由器,该值$-1$,为$0$时抛弃。
- 协议号:指明数据交付时使用的运输层协议,该字段将网络层与运输层绑定在一起。
IP编址
IP规定每台主机与每个路由器接口都必须要有一个IP地址,给定一个子网掩码,具有同样掩码前缀的设备构成一个子网。子网掩码这种层次编址的存在,大大减少了网络中路由器转发表的长度。IP地址可分为两部分,高位的网络地址与地位的主机地址,每隔8位做一次划分,则常用的IPv4地址可分为如下三类:
分类 | 开始地址 | 结束地址 | 网络地址位数 | 子网掩码 |
---|---|---|---|---|
A | 0.0.0.0 | 127.255.255.255 | 8 | 255.0.0.0 |
B | 128.0.0.0 | 191.255.255.255 | 16 | 255.255.0.0 |
C | 192.0.0.0 | 223.255.255.255 | 24 | 255.255.255.0 |
需要注意的是,主机地址全0用于表示一个网段,而主机地址全0则表示广播地址,即ABC三类地址下最多可分配的地址数还要减去这两个地址。除此之外,网络地址为127的IP是用于做环回测试的。
部分IP地址被设为私有IP地址,即局域网专用地址:
分类 | 开始地址 | 结束地址 | 网段 |
---|---|---|---|
A | 10.0.0.0 | 10.255.255.255 | 10.0.0.0/8 |
B | 172.16.0.0 | 172.31.255.255 | 172.16.0.0/12 |
C | 192.168.0.0 | 192.168.255.255 | 192.168.0.0/6 |
DHCP
每个主机与路由器接口的IP并不是与生俱来的,而是被分配的。DHCP(Dynamic Host Configuration Protocol)用于给接入网络的设备自动分配IP地址,DHCP服务器有一个IP地址池,每新加入一个客户机,DHCP服务器就为其分配地址。DHCP大大降低了IPv4地址数量的压力。
NAT
NAT(Network Address Translation)用于更好的管理局域网,同一个局域网内的机器拥有仅在局域网内才有效的局域网地址,而所有局域网机器对外界来说相当于只有一个公网IP。NAT路由器将公网端口与局域网机器映射起来,使得局域网机器能正常与外界通信。NAT的问题有两个,一是它需要消耗唯一公网IP的端口号,二是内网机器无法正常使用P2P应用。
链路层
链路层设备中最重要的就是网络接口(网络适配器),每一个网口都具有唯一的链路层地址,也叫MAC地址。MAC地址是一个静态的独一无二的地址,每个网络适配器被生产时就会被分配一个MAC地址。
ARP
IP协议是运行于网络层的协议,包括IP地址也位于网络层,在网络更底层中的数据传输需要完成IP地址到MAC地址的转换。ARP(Address Resolution Protocol)用于把IP地址转换成MAC地址。
每台主机会有自己的ARP缓存表(IP-MAC映射表),发送数据时,查找是否有目标IP对应的MAC地址,存在时则直接发送数据,否则需要发送ARP报文维护ARP表。ARP报文以广播形式发送给局域网络(以网段为单位),IP地址不匹配的主机不会做出响应,而IP匹配的主机会先将发送方的IP与MAC更新进ARP表中,然后发送应答报文。发送方更新ARP表,双方即可通信。
ARP的缺陷在于其完全依赖局域网络的安全性,若局域网中存在主机恶意应答ARP报文,会导致ARP表被篡改甚至失效,从而数据被拦截和重定向。使用静态ARP表可解决该问题。
有一种主动发送ARP报文的做法叫免费ARP(Gratuitous ARP),主机会主动向网络中发送自己的IP地址与MAC地址,这类报文是不期望得到回应的。若主机收到响应,则说明网络中已存在相同的IP,即产生了IP冲突。免费ARP的用途之一就是检测IP冲突。
RPC
远程过程调用(Remote Procedure Call),通俗地讲就是调用远程机器上的函数/方法。一个通俗的解释见这里。RPC需要解决的问题主要有如下几个:
- 通信;
- 函数定位,服务器如何准确知道客户端需要调用的是哪一个函数;
- 数据传输,跨平台跨语言条件下如何保持数据的一致性。
对通信而言,理论上各种网络协议都是可以使用的,常用的有TCP和HTTP;函数定位可以在客户端与服务器端都设置相对应的映射表来实现;数据传输涉及到序列化与反序列化,一般转成字节流进行传输。
Python内置的xmlrpc
库实现了XML-RPC,其使用XML封装数据,传输协议采用HTTP。一个简单的示例见此。