zoukankan      html  css  js  c++  java
  • TCP

    TCP特性

    • TCP提供一种面向连接的、可靠的字节流服务
    • 在一个TCP连接中,仅有两方进行彼此通信。广播和多播不能用于TCP
    • TCP使用校验和,确认和重传机制来保证可靠传输
    • TCP使用累积确认
    • TCP使用滑动窗口机制来实现流量控制,通过动态改变窗口的大小进行拥塞控制

    三次握手与四次挥手

    三次握手的目的是连接服务器指定端口,建立TCP连接,并同步连接双方的序列号和确认号,交换TCP窗口大小信息。在socket编程中,客户端执行connect()时。将触发三次握手。

    (1)第一次握手(SYN=1, seq=x):

      客户端发送一个 TCP 的 SYN 标志位置1的包,指明客户端打算连接的服务器的端口,以及初始序号 X,保存在包头的序列号(Sequence Number)字段里。发送完毕后,客户端进入 `SYN_SEND` 状态。

    (2)第二次握手(SYN=1, ACK=1, seq=y, ACKnum=x+1):

      服务器发回确认包(ACK)应答。即 SYN 标志位和 ACK 标志位均为1。服务器端选择自己 ISN 序列号,放到 Seq 域里,同时将确认序号(Acknowledgement Number)设置为客户的 ISN 加1,即X+1。 发送完毕后,服务器端进入 `SYN_RCVD` 状态。

    (3)第三次握手(ACK=1,ACKnum=y+1)

      客户端再次发送确认包(ACK),SYN 标志位为0,ACK 标志位为1,并且把服务器发来 ACK 的序号字段+1,放在确定字段中发送给对方,并且在数据段放写ISN的+1。发送完毕后,客户端进入 `ESTABLISHED` 状态,当服务器端接收到这个包时,也进入 `ESTABLISHED` 状态,TCP 握手结束。第三次握手客户端已经可以发送携带数据的报文段了。

    TCP的连接的拆除需要发送四个包,因此称为四次挥手。客户端或服务器均可主动发起挥手动作,在 socket 编程中,任何一方执行 close() 操作即可产生挥手操作。

    (1)第一次挥手(FIN=1,seq=x)

      假设客户端想要关闭连接,客户端发送一个 FIN 标志位置为1的包,表示自己已经没有数据可以发送了,但是仍然可以接受数据。发送完毕后,客户端进入 FIN_WAIT_1 状态。

    (2)第二次挥手(ACK=1,ACKnum=x+1)

      服务器端确认客户端的 FIN 包,发送一个确认包,表明自己接受到了客户端关闭连接的请求,但还没有准备好关闭连接。发送完毕后,服务器端进入 CLOSE_WAIT 状态,客户端接收到这个确认包之后,进入 FIN_WAIT_2 状态,等待服务器端关闭连接。

    (3)第三次挥手(FIN=1,seq=y)

      服务器端准备好关闭连接时,向客户端发送结束连接请求,FIN 置为1。发送完毕后,服务器端进入 LAST_ACK 状态,等待来自客户端的最后一个ACK。

    (4)第四次挥手(ACK=1,ACKnum=y+1)

      客户端接收到来自服务器端的关闭请求,发送一个确认包,并进入 TIME_WAIT状态,等待可能出现的要求重传的 ACK 包。服务器端接收到这个确认包之后,关闭连接,进入 CLOSED 状态。

      客户端等待了某个固定时间(两个最大段生命周期,2MSL,2 Maximum Segment Lifetime)之后,没有收到服务器端的 ACK ,认为服务器端已经正常关闭连接,于是自己也关闭连接,进入 CLOSED 状态。

    为什么一定要进行三次握手呢?

        前两次的握手很显然是必须的,主要是最后一次,即客户端收到服务端发来的确认后为什么还要想服务端再发送一次确认呢?这主要是为了防止已失效的请求报文段突然又传送到了服务端而产生连接的误判。

        考虑如下的情况:客户端发送了一个连接请求报文段到服务端,但是在某些网络节点上长时间滞留了,而后客户端又超时重发了一个连接请求报文段该服务端,而后正常建立连接,数据传输完毕,并释放了连接。如果这时候第一次发送的请求报文段延迟了一段时间后,又到了服务端,很显然,这本是一个早已失效的报文段,但是服务端收到后会误以为客户端又发出了一次连接请求,于是向客户端发出确认报文段,并同意建立连接。假设不采用三次握手,这时服务端只要发送了确认,新的连接就建立了,但由于客户端并没有发出建立连接的请求,因此不会理会服务端的确认,也不会向服务端发送数据,而服务端却认为新的连接已经建立了,并在一直等待客户端发送数据,这样服务端就会一直等待下去,直到超出保活计数器的设定值,而将客户端判定为出了问题,才会关闭这个连接。这样就浪费了很多服务器的资源。而如果采用三次握手,客户端就不会向服务端发出确认,服务端由于收不到确认,就知道客户端没有要求建立连接,从而不建立该连接。

    参考:TCP连接的建立和释放

    TCP的流量控制机制

      一般来说,我们总是希望数据传输的更快一些,但如果发送方把数据发送的很快,而接收方来不及接收,这就可能造成数据的丢失。流量控制就是让发送方的发送速率不要太快,让接收方来得及接收。

      对于成块数据流,TCP利用滑动窗口机制来实现流量的控制,假设A向B发送数据。在连接建立时,B告诉了A:“我的接收窗口是 rwnd = 400 ”(这里的 rwnd 表示 receiver window) 。因此,发送方的发送窗口不能超过接收方给出的接收窗口的数值。请注意,TCP的窗口单位是字节,不是报文段。再设每一个报文段为100字节长,而数据报文段序号的初始值设为1。大写ACK表示首部中的确认位ACK,小写ack表示确认字段的值。

      从图中可以看出,B进行了三次流量控制。第一次把窗口减少到 rwnd = 300 ,第二次又减到了 rwnd = 100 ,最后减到 rwnd = 0 ,即不允许发送方再发送数据了。这种使发送方暂停发送的状态将持续到主机B重新发出一个新的窗口值为止。

      我们考虑一种特殊情况,如果B在向A发送了零窗口报文段后不久,B的接收缓存又有了一些存储空间,于是B向A发送了一个rwnd=400的报文段,然而这个报文段在传送过程中丢失了,A就一直等待B发送非零窗口的报文通知,而B一直等待A发送数据,如果没有任何措施的话,死锁的局面会一直延续下去。

        为了解决这个问题,TCP为每一个连接设有一个持续计时器(也叫坚持定时器)。只要TCP连接的一方收到对方的零窗口通知,就启动持续计时器。若持续计时器设置的时间到期,就发送一个零窗口控测报文段(携1字节的数据),对方在收到探测报文段后,在对该报文段的确认洪给出现在的窗口值,如果窗口值仍未零,则收到这个报文段的一方就重新设置持续计时器,如果窗口不为零,那么死锁的僵局就被打破了。

    参考:TCP的流量控制机制

    参考:TCP的拥塞控制机制

     TCP中的四大定时器

    (1)重传定时器
      重传定时器是用来计算TCP报文段的超时重传时间的。每发送一个报文段就会启动重传定时器,如果在定时器时间到后还没收到对该报文段的确认,就重传该报文段,并将重传定时器复位,重新计算;如果在规定时间内收到了对该报文段的确认,则撤销该报文段的重传定时器。

    (2)坚持定时器
      主要是为了应付零窗口大小通知可能导致的死锁问题。如果接收端在向发送端发送了零窗口报文段后不久,接收端的接收缓存又有了一些存储空间,于是接收端向发送端发送了一个非零窗口大小的报文段,然而这个报文段在传送过程中丢失了,发送端没有收到该报文段,就一直等待接收端发送非零窗口的报文通知,而接收端并不知道报文段丢失了,而是觉得已经告诉发送端了,就会一直等待发送端发送数据,如果没有任何措施的话,这话死锁的局面会一直延续下去。

      为了解决这个问题,TCP为每一个连接设有一个坚持定时器(也叫持续计数器)。只要TCP连接的一方收到对方的零窗口通知,就启动坚持定时器。若坚持定时器设置的时间到期,就发送一个零窗口控测报文段(该报文段只有一个字节的数据,它有一个序号,但该序号永远不需要确认,因此该序号可以持续重传),之后会出现以下三种情况:
      1、对方在收到探测报文段后,在对该报文段的确认中给出现在的窗口值,如果窗口值仍未零,则收到这个报文段的一方将坚持定时器的值加倍并重启。坚持计数器最大只能增加到约60秒,在此之后,每次收到零窗口通知,坚持计数器的值就定位60秒。
      2、对方在收到探测报文段后,在对该报文段的确认中给出现在的窗口值,如果窗口不为零,那么死锁的僵局就被打破了。
      3、该探测报文发出后,会同时启动重传定时器,如果重传定时器的时间到期,还没有收到接收到发来的响应,则超时重传探测报文。
    (3)保活定时器
      保活定时器是为了应对两个TCP连接间出现长时间的没有数据传输的情况。如果客户已与服务器建立了TCP连接,但后来客户端主机突然故障,则服务器就不能再收到客户端发来的数据了,而服务器肯定不能这样永久地等下去,保活定时器就是用来解决这个问题的。服务器每收到一次客户端的数据,就重新设置保活定时器,通常为2小时,如果2小时没有收到客户端的数据,服务端就发送一个探测报文,以后每隔75秒发送一次,如果连续发送10次探测报文段后仍没有收到客户端的响应,服务器就认为客户端出现了故障,就可以终止这个连接。

    (4)2MSL定时器
      2MSL定时器测量一个连接处于TIME—WAIT等待的时间,通常为2MSL(报文段寿命的两倍)。2MSL定时器的设置主要是为了确保发送的最后一个ACK报文段能够到达对方,并防止之前与本连接有关的由于延迟等原因而导致已失效的报文被误判为有效。

    问题:在网络7层协议中,如果想使用UDP协议达到TCP协议的效果,可以在哪层做文章?

    答案:会话层
    因为UDP要达到TCP的功能就必须实现拥塞控制的功能,而且是在路由之间实现,这个在底层明显是做不到拥塞控制的,在应用层也是做不到的,因为应用层之间和应用程序挂钩,一般只能操控主机的程序,而表示层是处理所有与数据表示及运输有关的问题,包括转换、加密和压缩,在传输层是不可能的,因为你已经使用了UDP协议,无法在本层转换它,只有在会话层.
    会话层(SESSION LAYER)允许不同机器上的用户之间建立会话关系。会话层循序进行类似的 传输层 的普通数据的传送,在某些场合还提供了一些有用的增强型服务。允许用户利用一次会话在远端的分时系统上登陆,或者在两台机器间传递文件。 会话层提供的服务之一是管理对话控制。会话层允许信息同时双向传输,或任一时刻只能单向传输。如果属于后者,类似于物理信道上的半双工模式,会话层将记录此时该轮到哪一方。

     

  • 相关阅读:
    包括”/“排除”设置禁用了加载功能。
    如何打造高质量的机器学习数据集?
    机器学习项目流程(一)初探数据集
    java 转义与反转义
    jfinal 获取刚保存的对象的主键 ,该主键在数据库中自增
    凤凰架构:构建可靠的大型分布式系统 ISBN:9787111683919 -推荐
    STC89C52控制74HC595,74HC138双色16x16点阵屏循环显示汉字
    STC89C52驱动MAX7219LED点阵级联, 文字滚动效果
    STM32F407VET6烧录出现flash download failed target dll has been cancelled
    DS1302与STC12的连接电路和驱动实现
  • 原文地址:https://www.cnblogs.com/hesier/p/5886550.html
Copyright © 2011-2022 走看看