重拾大学课本《计算机网络》,回顾IP、TCP、UDP、HTTP的数据报解析
在计算机网络中要做到有条不紊的交换数据,我们必须得遵守一些事先约定好的规则。这些为进行网络中数据而建立的规则、标准或者约定成为网络协议。网络协议是计算机网络中不可缺少的组成部分。只要我们想让连接在网络上的另一台机器做点什么事情,我们都需要有协议。
计算机网络是个非常复杂的系统,假定我们有一个非常简单的需求:连接在网络上的主机1和主机2进行文件传输。
首先,必须要确保两台机器间必须要有一条传送数据的通道,但这还远远不够,至少还要有如下的工作:
- 发送通信的机器(以下称发起方)必须要将数据通信的通道进行激活(active).所谓的激活就是发送一些信令,保证要传送的数据能在这条通道上正确的发送和接收。
- 告诉网络如何识别接收方
- 发起方检查能否与接收方正常通信(接收方是否开机,是否连接网络等)
- 发起方的应用程序必须要弄清楚,接收方是否已经做好接收文件和存储文件的准备
- 若发起方和接收方的文件格式不兼容,至少有一方要完成格式转换。
- 对出现的各种差错和意外(如数据传送错误,重复或丢失,网络节点交换机出现故障),应当有可靠的保障措施保证接收方能够正确的接收文件。
除了以上的工作,还可以列举出一些其他要做的工作,由此可见,相互通信的两个计算机系统必须高度协调工作才行,这种“协调”是相当复杂的,为了设计这样复杂的计算机网络,早在最初的ARPNET设计时即提出了“分层”的方法。
计算机网络中的各层以及其协议的集合就成为网络的体系架构。
计算机网络体系架构
- OSI七层协议体系结构的概念清楚,理论也比较完整,但它复杂又不实用。
- TCP/IP体系结构是一个四层协议,它得到了非常广泛的应用,(实际上TCP/IP只有最上面的三层,因为最下面的网络接口层并没有什么具体内容)
- 五层架构:综合了OSI和TCP/IP的优点,采用了只有五层协议的体系架构,这样即简介又能将概念阐述清楚(五层架构只是为了介绍网络原理而设计的,实际运用还是TCP/IP四层体系架构)
下图说明的是引用进程的数据在各层之间的传递过程中所经历的变化。这里为了简单 起见,假定两台机器是通过一个路由器连接起来的:
TCP/IP体系架构
在互联网使用的各种协议汇总,最重要的和最广泛运用的就是TCP和IP两个协议。现在人们提到TCP/IP并不一定是指TCP和IP这两个具体的协议,而往往标识互联网所使用的整个TCP/IP协议族。
IP
TCP/IP协议定义了一个在网际层上传输的包,称为IP数据包,而IP数据报(IP Datagram)。
一个IP数据报是由首部和数据部分两部分组成的。
首部是前一部分是固定长度20字节,固定部分后面是一些可选字段,长度是可变的。
在TCP/IP标准中,各种数据常常以32位(4字节)为单位来描述。
IP数据报首部固定部分
1. 版本 :占4位,指IP协议的版本。通信双方的IP版本必须保持一致。IPV4(版本值为4),IPV6(版本值为6)。
2. 首部长度:占4位,表示的最大十进制值为15;首部长度表示的单位是32位字(4字节)。所以首部长度最大值为 15*4 = 60字节,而首部=固定长度(20) + 可选字段;即首部最小值是20字节,即首部长度最小值是20/4=5 (0101);当首部长度为5,即首部为20字节时,无需可选字段。,可变部分最大40字节(60-20 = 40)
3. 区分服务(DiffServ(DS)):占8位,用来获取更好的服务,在旧的标准中叫做服务类型,它的作用是力图不改变网络的基础结构,但在路由器中增加区分服务的功能.DS目前只利用前6位,即区分服务码点DSCP(Different Services CodePoint),后两位目前不使用,记为CU(Currently Unused)。DSCP优先级值有64个(0-63),0优先级最低,63优先级最高。
4. 总长度:占16位,首部和数据之和的长度,单位为字节。所以数据报的最大长度65535字节。实际上这样长度的数据报在现实中是极少遇到的。在IP层下的每一种数据链路层协议都规定了一个数据帧中数据字段的最大长度,这成为最大传送单元(MTU Maximum Transfer Unit)。例如,最常用的以太网规定其MTU值是1500字节.
5. 标识:占16位,IP软件在存储器中维持一个计数器,每产生一个数据报,计数器就加1,并将这个值赋给此字段.(这个标识不是序号,因为当数据报的长度大于MTU时,就必须要分片,同一个数据报的所有分片的的标识字段相同,这样相同标识字段的值使分片后最后能重装成原来的数据报(结合后续的片偏移))
6. 标志: 占3位。最高位保留,后两位使用。
7. 片偏移:占13位,较长的分组在分片时,某片在原分组中的相对位置。即相对于用户数据字段的起点,该片从何处开始。片偏移以8个字节为偏移单位(64位)
8. 生存时间:占8位,TTL(Time To Live)。之前TTL的单位是秒,在路由器消耗的时间小于1秒时,就把TTL值减1.当TTL值减为0时,就丢弃这个数据报。 后来随着技术的更新,报文在路由器中处理的时间远远小于1秒,后来TTL字段的功能改为“跳数限制”。路由器在每次转发数据报之前就把TTL值减1.
9. 协议:占8位。协议字段告知目的主机的ip层将数据交给哪个协议进行处理:
10. 首部校验和:占16位,只校验数据报的首部,但不包括数据部分。
11. 源地址:32位(IPV6是128位)
12. 目标地址:32位
IP数据报首部可变部分
IP数据报首部的可变部分就是一个选项字段。选项字段用来支持排错,测量以及安全等措施。此字段长度从1到40字节(也可为0,为0时表示没有可选字段)。
UDP
UDP 是用户数据报协议(User Datagram Protocol)的简称,它是运输层协议。它只是在IP数据报服务上增加了很少的功能,就是复用和分用以及差错检测功能。UDP的特点
- UDP是无连接的:即发送数据之前不需要建立连接
- UDP使用尽最大努力交付,即不保证可靠交付
- UDP是面向报文的。发送方的对应用程序交下来的报文,在添加首部后就交付给IP层。UDP对应用层交下来的报文,即不合并,也不拆分,而是保留这些报文的边界。也就是说应用层交给UDP多长的报文,UDP就照样发送,即一次发送一个完整的报文,接收方的UDP,对IP层交上来的UDP用户数据报文,去除首部后原封不动的上交给应用程序。所以应用程序必须要选择合适的报文大小。
- UDP没有拥塞控制:网络出现的拥塞不会使源主机的发送速率降低。—比如说网络直播在网络拥塞时允许丢失一些数据,却不允许有太大的延时。
- UDP支持一对一,一对多,多对多的交互通信
- UDP首部开销小: 只有8个字节,比TCP(20字节)的首部要短。
用户数据报UDP有两个字段:数据字段和首部字段,首部字段很简单,只有8个字节,由四个字段组成,每个字段长度都是两个字节。
- 源端口 : 需要对方回信时选用,不需要时全0
- 目标端口: 目标端口号,这在重点交付报文时必须使用。若接收方不存在目标端口的应用进程,则由网际控制报文协议ICMP发送“端口不可达”差错报文给发送方。
- 长度: UDP数据报长度,最小值为8(仅有UDP首部)
- 检验和: 检验UDP数据报在传输中是否有错,有错就丢弃。它是把首部和数据部分一起都检验的
UDP数据报首部检验和的计算方法有些特殊,要在UDP用户数据报之前增加12字节的伪首部,它并不是数据报的真正的首部,只是在检验和时,临时添加在UDP数据报前面,得到一个临时的UDP数据报。检验和就是按照这个临时的UDP数据报来计算的。伪首部即不向下传递,也不向上上交。
伪首部 - 第一、二字段:源IP和目标IP
- 第三个字段: 全是0
- 第四个字段:IP首部中协议字段的值(UDP:17)
- 第五个字段:UDP数据报的长度。
由此可知UDP检验和即检验了源IP和目标IP,也检验了源端口和目标端口,也检验了UDP数据报的数据部分。
TCP
TCP(Transmission Control Protocol 传输控制协议)是一种面向连接的、可靠的、基于字节流的传输层通信协议.TCP是TCP/IP体系中非常复杂的一个协议。TCP协议最主要的特点:
- TCP是面向连接的运输层协议。应用程序在使用TCP协议通信之前,必须先建立TCP连接(三次握手)
- TCP连接只能有两个端点,即点对点通信重点内容
- TCP提供可靠交付的服务。通过TCP传送的数据,无差错、无丢失、不重复并且按序到达
- TCP提供全双工通信,TCP允许通信双方应用程序在任何时候都可以发送数据。TCP连接的两端都设有发送缓存和接收缓存,用来临时存放双向通信的数据。在发送时,发送方应用程序把数据传送给TCP的缓存后,就可以做其他的事情,在TCP适合的时候把数据发送出去;在接收时,TCP把收到的数据放到缓存,接收方上层应用程序在合适的时候取缓存中的数据。
- 面向字节流。TCP中的流指的是流入到进程或从进程流出的字节序列。TCP和UDP发送报文时采用的方式完全不同。TCP并不关心应用程序一次把多长的报文发送到TCP缓存中,而是根据对方窗口值和当前网络拥塞的程度来决定一个报文应该包含多少字节。(UDP发送的报文长度是应用程序给出的 )。如果应用程序传送到TCP缓存的数据块太长,TCP会把它划分短一些再传送出去。如果应用程序一次只发送一个字节,TCP也可以等待积累足够字节后再构成报文发出去。(TCP粘包和拆包)
TCP报文首部
TCP虽然是面向字节流的,但TCP传送的数据单元却是数据报。一个TCP报文段分为首部和数据两部分,而TCP的全部功能都体现在它的首部中个字段的作用。TCP首部的前20字节是固定的,后面有4n字节是根据需要而增加的选项,因此TCP首部最小长度是20字节。
- 源端口和目的端口:各占16位(2字节)。
- 序号:32位,序号范围是【0,2^32-1】即(4294967296个序号)。序号增加到2^32-1后,下个序号就变为0.TCP是面向字节流的,它传送的每一个字节都按顺序编号。 首部中序号字段,表示本报文段所发送的第一个字节的序号。例如:一个报文的序号301,携带的数据有100字节,就代表这报文段的第一个字节序号是301,最后一个字节序号是400.下一个报文段的数据序号就是401。。这个名称也被称为“报文段序号”.
确认号:32位,是期望收到下一个报文段的第一个子节点序号。
请注意:<若确认号=N,则表明:到序号N-1为止的所有数据都已正确收到>。数据偏移:占4位。它指出TCP报文段的数据起始处距离TCP**报文段的起始处有多远。这个字段实际指出了TCP首部的长度,**由于首部中有长度不定的选项字段,所以该字段是必要的。注意的是数据偏移占4位,最大十进制值是15,(数据偏移的单位是32位即4字节),因此TCP首部最大值是15*4=60字节,也就是说选项长度最大值是40字节。
- 保留:占6位,保留为今后使用,目前为0
- 紧急URG(URGent):URG=1时,表明紧急指针字段有效。它告诉系统报文段中有紧急数据,应尽快传送(相当于高优先级数据),无需按照原来排队的顺序来传送,直接把紧急数据插入到本报文段数据的最前面。
- 确认ACK(ACKnowledgment),当ACK=1时确认字段才有效。TCP规定,在连接建立之后所有传送的报文都必须把ACK置为1.
- 推送PSH(PuSH): 当两个应用进程进行交互式通信时,有一端希望在键入一个命令之后对方立即响应,发送方TCP把PSH置为1,这样就无需等待缓冲区填满了之后再发送出去。接收方TCP收到PSH=1的报文段,就尽快的推送给应用进程,也无需等待缓存区填满了再向上交付。 —-这种操作很少用。
- 复位RST(ReSeT):RST=1,表明TCP连接出现严重差错,必须释放连接,然后重新建立运输连接。它还可以用来决绝一个非法的报文或拒绝打开一个连接。
- 同步SYN(SYNchronization):在连接建立时用来同步序号。当SYN=1,ACK=0时,表明这是一个连接请求报文,若对方同意建立连接,则返回SYN=1,ACK=1。
- 终止FIN(FINish) 用来释放一个连接,当FIN=1时,表明此段报文的发送方数据已经发送完毕,并请求释放连接。
- 窗口:占用2字节,可以计算出最大值为64K字节。窗口指的是接收方的窗口(不是自己的发送窗口)。窗口值告诉对方,从本报文段首部的确认号算起,允许对方发送的数据量(单位是字节)。之所以有这个限制,是因为接收方的缓存空间是有限的。窗口值明确指出了现在允许对方发送的数据量。窗口值在动态变化着。
- 检验和 占2字节。检验和字段检验的范围包括首部和数据两个部分。和UDP用户数据报一样,在计算检验和时,要在TCP前面加上12字节的伪首部,不同的是要把第四个字段的17改为6(TCP协议号是6,UDP协议号是17)。
- 紧急指针:占2字节。 在URG=1时才有意义。它指出本报文段中的紧急数据的字节数(值得注意的是,即使敞口值为0,也可以发送紧急数据)
- 选项:可变字段,最大值40字节
- 窗口扩大选项 : 3字节,其中一个字节表示移位值S,TCP首部中的窗口位数从16增大到(16+S),而移位值最大允许使用的值是14,则窗口最大值增大到30位。
- 时间戳选项:占10字节。最主要的字段是时间戳字段4字节,时间戳回送回答字段4字节,时间戳字段的作用
- 计算往返时间RTT。发送方发送报文时将当前时间放入时间戳字段,接收方接收到报文时,把时间戳字段复制到时间戳回送回答字段。因此发送方接收到确认报文时,可以准确计算RTT
- 用于处理TCP序号超过2^32的情况,又称为防止序号绕回PAWS(Protect Against Wrapped Sequence numbers)
TCP是面向连接的协议,运输连接是用来传送TCP报文的。TCP运输连接到建立和释放是每一次面向连接通信中必不可少的部分。
TCP连接的建立采用客户服务器方式,主动发起连接建立的应用进程叫做客户端(Client),被动等待连接建立的应用进程叫做服务端(Server)
TCP连接的建立–三报文握手
TCP建立连接的过程叫做握手,握手需要在客户端和服务端机器之间交换三个TCP报文段。
RFC973(TCP标准文档)使用名称three way handshake, 被广泛的翻译为三次握手,但实际上这是在一次握手中交换了三个报文,并不是三次握手,有点像一次握手,上下摇晃三次。后来RFC973重新描述,three way(three message) handshake,三报文握手
- 最初TCP两端应用进程都是处于CLOSED(关闭)状态
- A主动打开(客户端A),B被动打开(服务端B)
- 一开始,服务端B创建传输控制块TCB,准备接受客户端请求,服务器进入LISTEN状态,等待客户端连接请求。
- 客户端A也创建传输控制块TCB,客户端打算建立TCP连接时向服务端B发送连接请求报文段:首部的同部位SYN=1,选择一个客户端自己的初始序号x.(TCP规定,SYN报文段不能携带数据,但是要消耗一个序号),此时客户端进入SYN-SENT(同步已发送)状态
- 服务端接收到客户端的连接请求后,如果同意建立连接,则向客户端发送确认报文段(SYN=1,ACK=1),确认号ack=x+1,同时也为自己选择一个序号y.(TCP规定,这个报文段也不能携带数据,但同样消耗一个序列号),这是服务端进入SYN-RCVD(同步收到)状态
- 客户端A接收到服务端的确认后,还要再次给服务端确认。确认报文ACK=1,确认号ack=y+1,而此时自己的序列号seq=x+1,(TCP规定,ACK报文段可以携带数据,但如果不携带数据则不用消耗seq),此时客户端进入ESTABLISHED(已建立连接)状态
- 服务端接收到A确认后,也进入ESTABLISHED(已建立连接)状态
TCP连接的释放–四报文握手
数据传送结束后,通信的双方都可以释放连接。
- A发出TCP连接释放报文段,并停止向B发送数据,主动关闭TCP连接。报文首部的终止控制位FIN=1,序号u(为已传送数据最后一个字节的序号+1)。此时A进入FIN-WAIT-1(终止等待1)(TCP规定,FIN报文段即使不携带数据也要消耗一个序号)
- B收到A的释放连接请求后,发出确认,确认号ack=u+1,而这个报文段的序号v(B已发送的数据的最后一个字节的序号+1),此时B进入了CLOSE-WAIT(关闭等待)。TCP服务器进程这时应通知高层应用进程,这是A–>B的连接就关闭了,这时候的TCP连接进入半关闭half-close,即A没有数据发送给B,但是B如果有数据发送给A,A仍然要接收。也就是说B–>A的连接没有关闭,这个状态仍然要持续一段时间
- A接收到B的确认后,进入FIN-WAIT-2(终止等待2),等待B发出连接释放报文段。
- B仍然会继续发送数据报文给A,持续一段时间后,当B已经没有发送给A的报文后,其应用进程就会通知TCP释放连接。B发出的报文FIN=1,序号为w(B在半关闭状态又发送了一些数据,w=这些数据中最后一个字节的序号+1),同时需要B还必须要重复上次已经发送过的确认号ack=u+1,这是B进入LAST-ACK(最后确认状态)
5.A接收到B的连接释放报文段后,必须对此发出确认。确认报文段中ACK=1,ack=w+1,而自己的序号是u+1(TCP标准,前一个已发送到FIN请求报文消耗了一个序号),然后进入TIME-WAIT(时间等待)状态。请注意,TCP连接现在还没有释放掉,必须经历时间等待计时器(TIME-WAIT timer)设置的时间2MLS后,A才能进入到CLOSE状态。时间MLS叫做最长报文段寿命(Maximum Segment Lifetime),RFC793建议设置为2分钟。
HTTP
http有两类报文:
- 请求报文:从客户端向服务端发送请求报文
- 响应报文:从服务器到客户端的应答。
请求报文-样例
响应报文-样例
响应码
- 1xx表示通知信息,
- 2xx表示成功(200:OK, 202:Accepted)
- 3xx表示重定向(301 Moved Permanently被请求的资源已永久移动到新位置)
- 4xx表示客户的差错
- 400:Bad Request,
- 401:Unauthorized,
- 403:Forbidden,
- 404:NOT found
- 5xx表示服务器的差错(500:Internal Server Error)