zoukankan      html  css  js  c++  java
  • TCP协议总结

      前一阵腾讯面试的时候被问到TCP协议相关的知识,当时许多知识点记不清了,回答的不是很好,今天就稍微总结一下。

      TCP(Transmission Control Protocol 传输控制协议)是一种面向连接的、可靠的、基于字节流的传输层通信协议。其中需要注意的是TCP协议属于OSI模型中的传输层,并且是面向连接的。同时,讲到TCP协议就不得不提到Socket接口,其是网络编程里的重要概念。我们在这里要明确什么是Socket接口:通俗的讲,Socket接口=IP地址+端口号。TCP协议中的三次握手和四次挥手往往是面试中的考查重点,下面我们着重讲一下:

      TCP协议的三次握手,先上图解:

      

      首先Client端发送连接请求报文,Server段接受连接后回复ACK报文,并为这次连接分配资源。Client端接收到ACK报文后也向Server段发生ACK报文,并分配资源,这样TCP连接就建立了。

      注意:在第二次握手和第三次握手时,服务器端和客户端分别为连接分配资源。

      请注意,上图是我从网上其他作者那里截的,是有错的。

      图中应该有四个信号:SYN,Seq number, ACK, ACK number。其中SYN代表数据包中的同步位,当需要建立连接时,将此位置位1,否则为0;ACK代表数据包中的确认位,同样的,当回应信号时,将此位置位1,否则为0;Seq number是客户端/主机端随机产生的序列码,用以标识数据流的序号,代表“我方的数据流从此序号开始”。ACK number是确认序列码,代表“我方将要接受下一个数据流的序号”,ACK number = 对方Seq number+1。因此我们可以看出来,上图中的ack其实想表达的意思是“ACK number”

      通过一个实例,我们对三次握手的理解会更深刻

      实例:

      IP 192.168.1.116.3337 > 192.168.1.123.7788: S 3626544836:3626544836

      IP 192.168.1.123.7788 > 192.168.1.116.3337: S 1739326486:1739326486 ack 3626544837

      IP 192.168.1.116.3337 > 192.168.1.123.7788: ack 1739326487,ack 1

      第一次握手:192.168.1.116发送位码syn=1,随机产生seq number=3626544836的数据包到192.168.1.123,192.168.1.123由SYN=1知道192.168.1.116要求建立联机;

      第二次握手:192.168.1.123收到请求后要确认联机信息,向192.168.1.116发送ack number=3626544837,syn=1,ack=1,随机产生seq=1739326486的包;

      第三次握手:192.168.1.116收到后检查ack number是否正确,即第一次发送的seq number+1,以及位码ack是否为1,若正确,192.168.1.116会再发送ack number=1739326487,ack=1,192.168.1.123收到后确认seq=seq+1,ack=1则连接建立成功。

      图解,包括通信双方IP地址、端口号,序列号(seq number)和确认号(ack number)

      注:以下数据截图通过网络抓包分析工具Wireshark获得。

          

      第一次握手的数据包标志位情况:

      第二次握手的数据包标志位情况:

      第三次握手的数据包标志位情况:

      有的同学可能会有疑问,为什么TCP建立连接时是三次握手而不是两次

      因为如果两次握手就建立连接,可能导致服务器端接收到过期的连接请求后建立连接,从而浪费资源。下面举个例子

      假设B是客户端Client,A是服务器端Server,如果两次握手就建立连接,可能导致下面的情况:

      B给A发送请求,由于某种原因,这个请求信号阻塞在某个路由处(但没有失败),而B以为请求信号发送失败,所以重新发了一个请求信号。A收到了这个请求信号,回了ACK、Seq和ACK number,B接受到ACK、Seq和ACK number后,连接建立,进行通信,传输数据,通信完毕后断开。结果这时候第一次发送的请求连接信号传到了A,A以为B又请求了一次新的连接,所以回ACK、Seq和ACK number,但由于B并没有请求新的连接,会无视A这一次的ACK、Seq和ACK number。此时对A来讲,连接已经建立了,其为此次连接分配的资源会一直等待下去。

      而多了第三次握手,只有A接收到B的ACK、Seq number、ACK number后,对A才意味着连接建立。即如果超过了等待的时间,A还未收到相应的ACK等信号,就会释放之前为其分配的资源。

      TCP四次挥手

      

      假设Client端发起中断连接请求,也就是发送FIN报文。Server端接到FIN报文后,意思是说"我Client端没有数据要发给你了",但是如果你还有数据没有发送完成,则不必急着关闭Socket,可以继续发送数据。所以你先发送ACK,"告诉Client端,你的请求我收到了,但是我还没准备好,请继续你等我的消息"。这个时候Client端就进入FIN_WAIT状态,继续等待Server端的FIN报文。当Server端确定数据已发送完成,则向Client端发送FIN报文,"告诉Client端,好了,我这边数据发完了,准备好关闭连接了"。Client端收到FIN报文后,"就知道可以关闭连接了,但是他还是不相信网络,怕Server端不知道要关闭,所以发送ACK后进入TIME_WAIT状态,如果Server端没有收到ACK则可以重传。“,Server端收到ACK后,"就知道可以断开连接了"。Client端等待了2MSL后依然没有收到回复,则证明Server端已正常关闭,那好,我Client端也可以关闭连接了。Ok,TCP连接就这样关闭了!

      注意:中断连接端可以是Client端,也可以是Server端

      这里需要注意的是,Client发ACK相关信号后进入TIME_WAIT状态,需要等待2MSL(MSL, Maximum Segment Lifetime, 报文最大生存时间),MSL是任何报文在网络上存在的最长时间(虽然查了很多资料,但我不清楚是“超过这个时间报文将被视作死亡,即再也无法到达目的地”,还是“超过这个时间的报文将在路由端被丢弃”,我个人倾向于前一种说法),RFC中规定MSL为2min,实际应用常用的是30s, 1min, 2min。

      之所以要等待,是为了防止“client端发送的ACK相关信号发送不成功,导致server端收不到这个ACK相关信号,从而无法关闭连接的情况出现”。为什么会出现这样的设计呢?因为本来Server端发送FIN后,要确定client收到这个FIN,代表双方都确认对方知道要关闭连接了,才关闭连接(确认的方法就是收到这个ACK相关信号,若没有收到,会判断FIN发送不成功,会重发FIN)。因而,如果Client端在2MSL中没有收到重发的FIN,意味着server收到了ACK相关信号,不会出现server因为没收到ACK而无法关闭连接的情况,这个时候Client也就可以放心的关闭连接了。注:2MSL = max( ACK_time ) + max( 重发的FIN_time )

      关于TCP协议的相关知识就先讲到这里,其他的诸如“超时重传”与“拥塞处理”的知识下次再写。

      参考连接:

      1、TCP协议中的三次握手和四次挥手(图解)  http://blog.csdn.net/whuslei/article/details/6667471

      2、TCP通信的三次握手和四次撒手的详细流程(顿悟)http://www.cnblogs.com/cy568searchx/p/3711670.html

      3、TCP三次握手连接及seq和ack号的正确理解 http://blog.chinaunix.net/uid-25513153-id-187780.html

      4、TCP 的那些事儿(上) http://kb.cnblogs.com/page/209100/

      5、TCP三次握手详解及释放连接过程 http://blog.csdn.net/oney139/article/details/8103223

      6、TCP为什么需要3次握手与4次挥手 http://blog.csdn.net/xifeijian/article/details/12777187

      7、TCP为什么要三次握手,不是两次四次? http://blog.chinaunix.net/uid-20726927-id-2455485.html

  • 相关阅读:
    iOS-申请开发证书流程
    iOS-代理
    进程和线程
    iOS单例模式
    Switch语句
    枚举类型
    程序的三种结构
    运算符
    Swift项目开发中的一些必备数据
    Swift开发中常用的一些图片处理方法
  • 原文地址:https://www.cnblogs.com/ArsenalfanInECNU/p/4856579.html
Copyright © 2011-2022 走看看