计算机网络总结

1. 概述

  • OSI的七层协议结构的概念清楚,理论也比较完整,但它既复杂又不实用。TCP/IP体系结构不同,它现在已经得到了非常广泛的应用。学习计算机网络的原理往往采用折中的办法,综合OSI和TCP/IP的优点,采用五层协议的体系结构
计算机网体系结构

2.物理层

数据单位

  • 比特 0/1

根据信号中代表消息的参数取值方式不同,信号可分为两大类

  • 模拟信号 或连续信号 代表消息的参数的取值是连续的。
  • 数字信号 或离散信号 代表消息的参数的取值是离散的。

根据信息在传输线上的传送方向,分为以下三种通信方式:

  • 单工通信:单向传输
  • 半双工通信:双向交替传输
  • 全双工通信:双向同时传输

3.数据链路层

数据单元

    • 在一段数据前后分别添加首部和尾部,这样构成一个桢
    • 每一种链路层协议都规定了所能传送的帧的数据部分长度上限——最大传送单元 MTU
      • MTU的默认值是1500字节。在RFC 1661中,MTU叫做 最大接收单元 MRU
用帧首部和帧尾部封装成帧

4.网络层

设计思路

  • 电信网 传统电信网的主要业务是提供电话服务。电信网使用昂贵的程控交换机(其软件也非常复杂),用面向连接 的通信方式,使电信网络能够向用户(实际上就是电话机)提供可靠传输的服务。
  • 互联网采用的设计思路 网络层向上只提供简单灵活的、无连接的、尽最大努力交付的数据报服务 (2) 。这里的“数据报”(datagram)是互联网的设计者最初使用的名词,其实数据报(或IP数据报)就是我们经常使用的“分组”。数据报和分组是同义词,可以混用。网络在发送分组时不需要先建立连接。每一个分组(也就是IP数据报)独立发送,与其前后的分组无关(不进行编号)。网络层不提供服务质量的承诺 。也就是说,所传送的分组可能出错、丢失、重复和失序(即不按序到达终点),当然也不保证分组交付的时限。由于传输网络不提供端到端的可靠传输服务,这就使网络中的路由器比较简单,且价格低廉(与电信网的交换机相比较)。如果主机(即端系统)中的进程之间的通信需要是可靠的,那么就由网络的主机中的运输层负责(包括差错处理、流量控制等)。
  • 采用这种设计思路的好处是:网络造价大大降低,运行方式灵活,能够适应多种应用。互联网能够发展到今日的规模,充分证明了当初采用这种设计思路的正确性。
    网络层提供的两种服务

IP地址与硬件地址

IP地址与硬件地址的区别

数据单位 IP数据报

IP数据报的格式
  • 版本  占4位,指IP协议的版本。通信双方使用的IP协议的版本必须一致。目前广泛使用的IP协议版本号为4(即IPv4)
  • 首部长度  占4位,可表示的最大十进制数值是15。请注意,首部长度字段所表示数的单位是32位字(1个32位字长是4字节)。因为IP首部的固定长度是20字节,因此首部长度字段的最小值是5(即二进制表示的首部长度是0101)。而当首部长度为最大值1111时(即十进制数的15),就表明首部长度达到最大值15个32位字长,即60字节。当IP分组的首部长度不是4字节的整数倍时,必须利用最后的填充字段加以填充。因此IP数据报的数据部分永远在4字节的整数倍时开始,这样在实现IP协议时较为方便。首部长度限制为60字节的缺点是有时可能不够用。但这样做是希望用户尽量减少开销。最常用的首部长度是20字节(即首部长度为0101),这时不使用任何选项。
  • 区分服务  占8位,用来获得更好的服务。这个字段在旧标准中叫做服务类型 ,但实际上一直没有被使用过。1998年IETF把这个字段改名为区分服务 DS(Differentiated Services)。只有在使用区分服务时,这个字段才起作用(见8.4.4节)。在一般的情况下都不使用这个字段[RFC 2474,3168,3260]。
  • 总长度  总长度指首部和数据之和的长度,单位为字节。总长度字段为16位,因此数据报的最大长度为2 16 –1=65535字节。然而实际上传送这样长的数据报在现实中是极少遇到的。
  • 标识 (identification) 占16位。IP软件在存储器中维持一个计数器,每产生一个数据报,计数器就加1,并将此值赋给标识字段。但这个“标识”并不是序号,因为IP是无连接服务,数据报不存在按序接收的问题。当数据报由于长度超过网络的MTU而必须分片时,这个标识字段的值就被复制到所有的数据报片的标识字段中。相同的标识字段的值使分片后的各数据报片最后能正确地重装成为原来的数据报。
  • 标志 (flag) 占3位,但目前只有两位有意义。

标志字段中的最低位记为MF (More Fragment)。MF=1即表示后面“还有分片 ”的数据报。MF=0表示这已是若干数据报片中的最后一个。
标志字段中间的一位记为DF (Don't Fragment),意思是“不能分片 ”。只有当DF=0时才允许分片。

  • 片偏移  占13位。片偏移指出:较长的分组在分片后,某片在原分组中的相对
    位置。也就是说,相对于用户数据字段的起点,该片从何处开始。片偏移以8个字节为偏移单位。这就是说,每个分片的长度一定是8字节(64位)的整数倍。

  • 生存时间  占8位,生存时间字段常用的英文缩写是TTL(Time To Live),表明这是数据报在网络中的寿命 。由发出数据报的源点设置这个字段。其目的是防止无法交付的数据报无限制地在互联网中兜圈子(例如从路由器R 1 转发到R 2 ,再转发到R 3 ,然后又转发到R 1 ),因而白白消耗网络资源。最初的设计是以秒作为TTL值的单位。每经过一个路由器时,就把TTL减去数据报在路由器所消耗掉的一段时间。若数据报在路由器消耗的时间小于1秒,就把TTL值减1。当TTL值减为零时,就丢弃这个数据报。

  • 协议  占8位,协议字段指出此数据报携带的数据是使用何种协议,以便使目的主机的IP层知道应将数据部分上交给哪个协议进行处理。

    image.png

  • 首部检验和  占16位。这个字段只检验数据报的首部,但不包括数据部分 。

  • 源地址  占32位。

  • 目的地址  占32位。

5.运输层

概述

  • 在网络层,IP数据报首部中的检验和字段,只检验首部是否出现差错而不检查数据部分。
    根据应用程序的不同需求,运输层需要有两种不同的运输协议,面向连接的TCP无连接的UDP
使用UDP和TCP协议的各种应用和应用层协议

进程之间的通信

  • 复用

    • 是指在发送方不同的应用进程都可以使用同一个运输层协议传送数据
  • 分用

    • 指接收方的运输层在剥去报文的首部后能够把这些数据正确交付目的应用进程
  • 问题:两台主机进行通信就是两台主机中的应用进程互相通信,为了使运行不同操作系统的计算机的应用进程能够互相通信,就必须用统一的方法?

    • 解决问题方法 在运输层使用协议端口号 简称 端口
      • 协议端口是软件端口,和路由器或交换机上的硬件端口是完全不同的概念。硬件端口是不同硬件设备
    • 虽然通信的终点是应用进程,但只要把所传送的报文交到目的主机的某个合适的目的端口,剩下的工作(即最后交付目的进程)就由TCP或UDP来完成。
  • 端口

  • TCP/IP的运输层用一个16位端口号(65535个不同端口) 来标志一个端口,端口号只具有本地意义 ,它只是为了标志本计算机 应用层中的各个进程在和运输层交互时的层间接口

  • 分类

    • 服务器端使用的端口号
      • 熟知端口号/系统端口号

        • IANA(互联网名称与数字地址分配机构,这些数值可在网址www.iana.org查到。)把这些端口号指派给了TCP/IP最重要的一些应用程序,让所有的用户都知道。一种新的应用程序出现后,IANA是负责协调一些使Internet正常运作的机构)必须为它指派一个熟知端口,否则互联网上的其他应用进程就无法和它进行通信。
        • 常用的熟知端口号
      • 登记端口

        • 数值为1024~49151,是为没有熟知端口号的应用程序使用的。使用这类端口号必须在IANA按照规定的手续登记,以防止重复。
    • 客户端使用的端口号
      • 数值为49152~65535。留给客户进程选择暂时使用。当服务器进程收到客户进程的报文时,就知道了客户进程所使用的端口号,因而可以把数据发送给客户进程。通信结束后,刚才已使用过的客户端口号就不复存在,这个端口号就可以供其他客户进程使用。

运输层的端口

UDP 特点

  1. UDP是无连接的 ,即发送数据之前不需要建立连接
  2. UDP使用尽最大努力交付 ,即不保证可靠交付,因此主机不需要维持复杂的连接状态表
  3. UDP是面向报文 的。发送方的UDP对应用程序交下来的报文,在添加首部后就向下交付IP层。UDP对应用层交下来的报文,既不合并,也不拆分,而是保留这些报文的边界
  4. UDP没有拥塞控制 ,因此网络出现的拥塞不会使源主机的发送速率降低
  5. UDP支持一对一、一对多、多对一和多对多的交互通信
  6. UDP的首部开销小 ,只有8个字节,比TCP的20个字节的首部要短。

UDP首部格式

UDP用户数据报的首部和伪首部
  • 源端口  源端口号。在需要对方回信时选用。不需要时可用全0。

  • 目的端口  目的端口号。这在终点交付报文时必须使用。

  • 长度  UDP用户数据报的长度,其最小值是8(仅有首部)。

  • 检验和  检测UDP用户数据报在传输中是否有错。有错就丢弃。

  • 伪首部 计算校验和时,临时添加的。

TCP 特点

  1. TCP是面向连接的运输层协议 。这就是说,应用程序在使用TCP协议之前,必须先建立TCP连接。在传送数据完毕后,必须释放已经建立的TCP连接。也就是说,应用进程之间的通信好像在“打电话”:通话前要先拨号建立连接,通话结束后要挂机释放连接。
  2. 每一条TCP连接只能有两个端点(endpoint),每一条TCP连接只能是点对点的(一对一)。
  3. TCP提供可靠交付 的服务。通过TCP连接传送的数据,无差错、不丢失、不重复,并且按序到达。
  4. TCP提供全双工通信
  5. 面向字节流 。TCP中的“流”(stream)指的是流入到进程或从进程流出的字节序列 。“面向字节流”的含义是:虽然应用程序和TCP的交互是一次一个数据块(大小不等),但TCP把应用程序交下来的数据仅仅看成是一连串的无结构的字节流 。TCP并不知道所传送的字节流的含义。TCP不保证接收方应用程序所收到的数据块和发送方应用程序所发出的数据块具有对应大小的关系(例如,发送方应用程序交给发送方的TCP共10个数据块,但接收方的TCP可能只用了4个数据块就把收到的字节流交付上层的应用程序)。但接收方应用程序收到的字节流必须和发送方应用程序发出的字节流完全一样。当然,接收方的应用程序必须有能力识别收到的字节流,把它还原成有意义的应用层数据。

TCP报文段的首部格式

TCP报文段的首部格式
  • 源端口和目的端口  各占2个字节,分别写入源端口号和目的端口号。和前面图5-6所示的UDP的分用相似,TCP的分用功能也是通过端口实现的。
  • 序号  占4字节。序号范围是[0,2 32 –1],共2 32 (即4 294 967 296)个序号。序号增加到2 32 –1后,下一个序号就又回到0。也就是说,序号使用mod 2 32 运算。TCP是面向字节流的。在一个TCP连接中传送的字节流中的每一个字节都按顺序编号 。整个要传送的字节流的起始序号必须在连接建立时设置。首部中的序号字段值则指的是本报文段 所发送的数据的第一个字节的序号。例如,一报文段的序号字段值是301,而携带的数据共有100字节。这就表明:本报文段的数据的第一个字节的序号是301,最后一个字节的序号是400。显然,下一个报文段(如果还有的话)的数据序号应当从401开始,即下一个报文段的序号字段值应为401。这个字段的名称也叫做“报文段序号 ”。
  • 确认号  占4字节,是期望收到对方下一个报文段的第一个数据字节的序号 。例如,B正确收到了A发送过来的一个报文段,其序号字段值是501,而数据长度是200字节(序号501~700),这表明B正确收到了A发送的到序号700为止的数据。因此,B期望收到A的下一个数据序号是701,于是B在发送给A的确认报文段中把确认号置为701。请注意,现在的确认号不是501,也不是700,而是701。
  • 数据偏移  占4位,它指出TCP报文段的数据起始处距离TCP报文段的起始处有多远。这个字段实际上是指出TCP报文段的首部长度。由于首部中还有长度不确定的选项字段,因此数据偏移字段是必要的。但应注意,“数据偏移”的单位是32位字(即以4字节长的字为计算单位)。由于4位二进制数能够表示的最大十进制数字是15,因此数据偏移的最大值是60字节,这也是TCP首部的最大长度(即选项长度不能超过40字节)。
  • 保留  占6位,保留为今后使用,但目前应置为0
  • 紧急 URG(URGent) 当URG=1时,表明紧急指针字段有效。它告诉系统此报文段中有紧急数据,应尽快传送(相当于高优先级的数据),而不要按原来的排队顺序来传送。例如,已经发送了很长的一个程序要在远地的主机上运行。但后来发现了一些问题,需要取消该程序的运行。因此用户从键盘发出中断命令(Control+C)。如果不使用紧急数据,那么这两个字符将存储在接收TCP的缓存末尾。只有在所有的数据被处理完毕后这两个字符才被交付接收方的应用进程。这样做就浪费了许多时间。
  • 确认 ACK(ACKnowledgment) 仅当ACK=1时确认号字段才有效。当ACK=0时,确认号无效。TCP规定,在连接建立后所有传送的报文段都必须把ACK置1。
  • 推送 PSH(PuSH) 当两个应用进程进行交互式的通信时,有时在一端的应用进程希望在键入一个命令后立即就能够收到对方的响应。在这种情况下,TCP就可以使用推送(push)操作。这时,发送方TCP把PSH置1,并立即创建一个报文段发送出去。接收方TCP收到PSH=1的报文段,就尽快地(即“推送”向前)交付接收应用进程,而不再等到整个缓存都填满了后再向上交付。
  • 复位 RST(ReSeT) 当RST=1时,表明TCP连接中出现严重差错(如由于主机崩溃或其他原因),必须释放连接,然后再重新建立运输连接。RST置1还用来拒绝一个非法的报文段或拒绝打开一个连接。RST也可称为重建位或重置位。
  • 同步 SYN(SYNchronization) 在连接建立时用来同步序号。当SYN=1而ACK=0时,表明这是一个连接请求报文段。对方若同意建立连接,则应在响应的报文段中使SYN=1和ACK=1。因此,SYN置为1就表示这是一个连接请求或连接接受报文。关于连接的建立和释放,在后面讨论。
  • 终止 FIN(FINis,意思是“完”、“终”) 用来释放一个连接。当FIN=1时,表明此报文段的发送方的数据已发送完毕,并要求释放运输连接。
  • 窗口  占2字节。窗口值是[0,2 16 –1]之间的整数。窗口指的是发送本报文段的一方的接收窗口 (而不是自己的发送窗口)。窗口值告诉对方 :从本报文段首部中的确认号算起,接收方目前允许对方发送的数据量(以字节为单位)。之所以要有这个限制,是因为接收方的数据缓存空间是有限的。总之,窗口值作为接收方让发送方设置其发送窗口的依据 。
  • 检验和  占2字节。检验和字段检验的范围包括首部和数据这两部分。和UDP用户数据报一样,在计算检验和时,要在TCP报文段的前面加上12字节的伪首部。伪首部的格式与图5-5中UDP用户数据报的伪首部一样。但应把伪首部第4个字段中的17改为6(TCP的协议号是6),把第5字段中的UDP长度改为TCP长度。接收方收到此报文段后,仍要加上这个伪首部来计算检验和。若使用IPv6,则相应的伪首部也要改变。
  • 紧急指针  占2字节。紧急指针仅在URG=1时才有意义,它指出本报文段中的紧急数据的字节数(紧急数据结束后就是普通数据)。因此,紧急指针指出了紧急数据的末尾在报文段中的位置。当所有紧急数据都处理完时,TCP就告诉应用程序恢复到正常操作。值得注意的是,即使窗口为零时也可发送紧急数据。
  • 选项  长度可变,最长可达40字节。当没有使用“选项”时,TCP的首部长度是20字节。

TCP最初只规定了一种选项,即最大报文段长度 MSS(Maximum Segment Size)[RFC 879]。请注意MSS这个名词的含义。MSS是每一个TCP报文段中的数据字段的最大长度 。数据字段加上TCP首部才等于整个的TCP报文段。所以MSS并不是整个TCP报文段的最大长度,而是“TCP报文段长度减去TCP首部长度”。

TCP可靠传输的实现

以字节为单位的滑动窗口/连续ARQ协议
  • 位于发送窗口内的n个分组都可连续发送出去,而不需要等待对方的确认。这样,信道利用率就提高了
  • 发送方每收到一个确认,就把发送窗口向前滑动一个分组的位置。表示发送方收到了对第1个分组的确认,于是把发送窗口向前移动一个分组的位置。如果原来已经发送了前5个分组,那么现在就可以发送窗口内的第6个分组了。
  • 接收方一般都是采用累积确认 的方式。这就是说,接收方不必对收到的分组逐个发送确认,而是在收到几个分组后,对按序到达的最后一个分组发送确认 ,这就表示:到这个分组为止的所有分组都已正确收到了。
  • 累积确认有优点也有缺点。优点是:容易实现,即使确认丢失也不必重传。但缺点是不能向发送方反映出接收方已经正确收到的所有分组的信息。
超时重传时间的选择
  • TCP的发送方在规定的时间内没有收到确认就要重传已发送的报文段
  • TCP采用了一种自适应算法,它记录一个报文段发出的时间,以及收到相应的确认的时间。这两个时间之差就是报文段的往返时间RTT 。TCP保留了RTT的一个加权平均往返时间 RTT S (这又称为平滑的往返时间,S表示Smoothed。因为进行的是加权平均,因此得出的结果更加平滑)。每当第一次测量到RTT样本时,RTT S 值就取为所测量到的RTT样本值。但以后每测量到一个新的RTT样本,就按下式重新计算一次RTT S :


    image.png
选择确认SACK
  • 问题 这就是若收到的报文段无差错,只是未按序号,中间还缺少一些序号的数据,那么能否设法只传送缺少的数据而不重传已经正确到达接收方的数据?答案是可以的。选择确认就是一种可行的处理方法。
  • 如果要使用选择确认SACK,那么在建立TCP连接时,就要在TCP首部的选项中加上“允许SACK”的选项,而双方必须都事先商定好。如果使用选择确认,那么原来首部中的“确认号字段”的用法仍然不变。

TCP的拥塞控制方法

  • CP进行拥塞控制的算法有四种,即 慢开始 (slow-start)、拥塞避免 (congestion avoidance)、快重传 (fast retransmit)和 快恢复 (fast recovery)
  • 基于窗口 的拥塞控制。为此,发送方维持一个叫做拥塞窗口 cwnd(congestion window)的状态变量。拥塞窗口的大小取决于网络的拥塞程度,并且动态地在变化。发送方让自己的发送窗口等于拥塞窗口 。
  • 发送方控制拥塞窗口的原则是:只要网络没有出现拥塞,拥塞窗口就可以再增大一些,以便把更多的分组发送出去,这样就可以提高网络的利用率。但只要网络出现拥塞或有可能出现拥塞,就必须把拥塞窗口减小一些,以减少注入到网络中的分组数,以便缓解网络出现的拥塞 判断网络拥塞的依据就是出现了超时
慢开始
  • 思路 当主机开始发送数据时,由于并不清楚网络的负荷情况,所以如果立即把大量数据字节注入到网络,那么就有可能引起网络发生拥塞。经验证明,较好的方法是先探测一下,即由小到大逐渐增大发送窗口(每经过一个传输轮次,拥塞窗口 cwnd就加倍) ,也就是说,由小到大逐渐增大拥塞窗口数值 。

  • 旧的规定是这样的:在刚刚开始发送报文段时,先把初始拥塞窗口cwnd设置为1至2个发送方的最大报文段SMSS,新的RFC 5681把初始拥塞窗口cwnd设置为不超过2至4个SMSS(Sender Maximum Segment Size)的数值。具体的规定如下:

    • 若SMSS>2190字节, 则设置初始拥塞窗口cwnd=2×SMSS字节,且不得超过 2个报文段。
    • 若(SMSS>1095字节)且(SMSS≤2190字节), 则设置初始拥塞窗口cwnd=3×SMSS字节,且不得超过 3个报文段。
    • 若SMSS≤1095字节,则设置初始拥塞窗口cwnd=4×SMSS字节,且不得超过 4个报文段。
  • 慢开始规定,在每收到一个对新的报文段的确认 后,可以把拥塞窗口增加最多一个SMSS的数值。

  • 为了防止拥塞窗口cwnd增长过大引起网络拥塞,还需要设置一个慢开始门限

    • 当cwnd
    • 当cwnd>ssthresh时,停止使用慢开始算法而改用拥塞避免算法。
    • 当cwnd=ssthresh时,既可使用慢开始算法,也可使用拥塞避免算法。

拥塞避免

  • 思路 让拥塞窗口cwnd缓慢地增大,即每经过一个往返时间RTT就把发送方的拥塞窗口cwnd加1 而不是像慢开始阶段那样加倍增长。因此在拥塞避免阶段就有“加法增大 ”AI(Additive Increase)的特点。这表明在拥塞避免阶段,拥塞窗口cwnd按线性规律缓慢增长 ,比慢开始算法的拥塞窗口增长速率缓慢得多。
TCP拥塞窗口cwnd在拥塞控制时的变化情况

快重传算法

  • 让发送方尽早知道发生了个别报文段的丢失 。快重传算法首先要求接收方不要等待自己发送数据时才进行捎带确认,而是要立即发送确认 ,即使收到了失序的报文段 也要立即发出对已收到的报文段的重复确认

    快重传的示意图
  • 因此,上中的点➍,发送方知道现在只是丢失了个别的报文段。于是不启动慢开始,而是执行快恢复 算法。这时,发送方调整门限值ssthresh=cwnd/2=8,同时设置拥塞窗口cwnd=ssthresh=8(见上图中的点➎),并开始执行拥塞避免算法

快恢复算法

  • 发送方知道丢失了个别报文段,于是不启动慢开始,而是快恢复,(如 ssthresh=cwnd/2=8,同时设置拥塞窗口cwnd=ssthresh),然后执行拥塞避免
  • 也有算法 恢复实现是把快恢复开始时的拥塞窗口cwnd值再增大一些(增大3个报文段的长度),即等于新的ssthresh+3×MSS。这样做的理由是:既然发送方收到3个重复的确认,就表明有3个分组已经离开了网络。这3个分组不再消耗网络的资源而是停留在接收方的缓存中(接收方发送出3个重复的确认就证明了这个事实)。可见现在网络中并不是堆积了分组而是减少了3个分组。因此可以适当把拥塞窗口扩大些。
TCP的拥塞控制的流程图

TCP的连接建立

用三报文握手建立TCP连接

假定主机A运行的是TCP客户程序,而B运行TCP服务器程序。最初两端的TCP进程都处于CLOSED(关闭)状态。图中在主机下面的方框分别是TCP进程所处的状态。请注意,在本例中,A主动打开连接 ,而B被动打开连接 。

一开始,B的TCP服务器进程先创建传输控制块 TCB (15) ,准备接受客户进程的连接请求。然后服务器进程就处于LISTEN(收听)状态,等待客户的连接请求。如有,即作出响应。

A的TCP客户进程也是首先创建传输控制模块 TCB。然后,在打算建立TCP连接时,向B发出连接请求报文段,这时首部中的同步位SYN=1,ACK=0同时选择一个初始序号seq=x。TCP规定,SYN报文段(即SYN=1的报文段)不能携带数据,但要消耗掉一个序号 。这时,TCP客户进程进入SYN-SENT(同步已发送)状态。

B收到连接请求报文段后,如同意建立连接,则向A发送确认。在确认报文段中应把SYN位和ACK位都置1,确认号是ack=x+1,同时也为自己选择一个初始序号seq=y。请注意,这个报文段也不能携带数据,但同样要消耗掉一个序号 。这时TCP服务器进程进入SYN-RCVD(同步收到)状态。

TCP客户进程收到B的确认后,还要向B给出确认。确认报文段的ACK置1,确认号ack=y+1,而自己的序号seq=x+1。TCP的标准规定,ACK报文段可以携带数据。但如果不携带数据则不消耗序号 ,在这种情况下,下一个数据报文段的序号仍是seq=x+1。这时,TCP连接已经建立,A进入ESTABLISHED(已建立连接)状态。

当B收到A的确认后,也进入ESTABLISHED状态。

  • 三次握手的原因
    • 为了防止失效的连接请求到达服务器,让服务器错误打开连接
    • 如 客户端请求连接在网络中滞留,那么会隔很久才会收到服务器发回的确认,客户端等待 一个超时重传时间之后,就会重新请求连接。这个时候就会有两个连接。如果有第三次握手,客户端会忽略服务器之后发送的第二次连接确定。

TCP的连接释放

image.png

B收到连接释放报文段后即发出确认,确认号是ack=u+1,而这个报文段自己的序号是v,等于B前面已传送过的数据的最后一个字节的序号加1。然后B就进入CLOSE-WAIT(关闭等待)状态。TCP服务器进程这时应通知高层应用进程,因而从A到B这个方向的连接就释放了,这时的TCP连接处于半关闭 (half-close)状态,即A已经没有数据要发送了,但B若发送数据,A仍要接收。也就是说,从B到A这个方向的连接并未关闭,这个状态可能会持续一段时间。

A收到来自B的确认后,就进入FIN-WAIT-2(终止等待2)状态,等待B发出的连接释放报文段。

若B已经没有要向A发送的数据,其应用进程就通知TCP释放连接。这时B发出的连接释放报文段必须使FIN=1。现假定B的序号为w(在半关闭状态B可能又发送了一些数据)。B还必须重复上次已发送过的确认号ack=u+1。这时B就进入LAST-ACK(最后确认)状态,等待A的确认。

A在收到B的连接释放报文段后,必须对此发出确认。在确认报文段中把ACK置1,确认号ack=w+1,而自己的序号是seq=u+1(根据TCP标准,前面发送过的FIN报文段要消耗一个序号)。然后进入到TIME-WAIT(时间等待)状态。请注意,现在TCP连接还没有释放掉。必须经过时间等待计时器 (TIME-WAIT timer)设置的时间2MSL后,A才进入到CLOSED状态。时间MSL叫做最长报文段寿命 (Maximum Segment Lifetime),RFC 793建议设为2分钟。但这完全是从工程上来考虑的,对于现在的网络,MSL=2分钟可能太长了一些。因此TCP允许不同的实现可根据具体情况使用更小的MSL值。因此,从A进入到TIME-WAIT状态后,要经过4分钟才能进入到CLOSED状态,才能开始建立下一个新的连接。当A撤销相应的传输控制块TCB后,就结束了这次的TCP连接。

  • 四次挥手的原因

    • 客户端A发送FIN连接释放报文之后,服务器收到这个报文,进入CLOSE-WAIT。这个状态是为了让服务器发送还未传送完毕的数据,传送完毕之后,服务器会发送FIN连接释放报文
  • 为什么A在TIME-WAIT状态必须等待2MSL的时间呢?这有两个理由。

第一,为了保证A发送的最后一个ACK报文段能够到达B。这个ACK报文段有可能丢失,因而使处在LAST-ACK状态的B收不到对已发送的FIN+ACK报文段的确认。B会超时重传这个FIN+ACK报文段,而A就能在2MSL时间内收到这个重传的FIN+ACK报文段。接着A重传一次确认,重新启动2MSL计时器。最后,A和B都正常进入到CLOSED状态。如果A在TIME-WAIT状态不等待一段时间,而是在发送完ACK报文段后立即释放连接,那么就无法收到B重传的FIN+ACK报文段,因而也不会再发送一次确认报文段。这样,B就无法按照正常步骤进入CLOSED状态。

第二,防止上一节提到的“已失效的连接请求报文段”出现在本连接中。A在发送完最后一个ACK报文段后,再经过时间2MSL,就可以使本连接持续的时间内所产生的所有报文段都从网络中消失。这样就可以使下一个新的连接中不会出现这种旧的连接请求报文段。

B只要收到了A发出的确认,就进入CLOSED状态。同样,B在撤销相应的传输控制块TCB后,就结束了这次的TCP连接。我们注意到,B结束TCP连接的时间要比A早一些。

TCP粘包/拆包

  • 产生原因

    • 应用程序write写入的字节大小大于套接口发送缓冲区大小
      • 每个TCP套接口有一个发送缓冲区
    • 进行了MSS大小的TCP分段
      • MSS是每一个TCP报文段中的数据字段的最大长度 。数据字段加上TCP首部才等于整个的TCP报文段
    • 数据链路层 以太网的帧数据部分大于MTU进行了分片
      • 每一种链路层协议都规定了所能传送的帧的数据部分长度上限——最大传送单元 MTU
  • 解决方案

    • 消息定长,例如每个报文的大小为固定长度200字节,如果不够,空位补空格
    • 在包尾增加回车换行符进行分割,例如FTP协议
    • 将消息分为消息头和消息体,消息头中包含表示消息总长度(或者消息体长度)的字段,通常设计思路为消息头的第一个字段使用int32来表示消息的总长度
    • 用成熟工具。用netty 它解决这些问题。

应用层

你可能感兴趣的:(计算机网络总结)