小言_互联网的博客

看完这篇博客之后,含着泪学会了TCP/IP

267人阅读  评论(0)

前言:

转载请附上连接,本帖原创请勿照抄。

  TCP/IP在日常生活中的方方面面都是使用到,如果忽然某天有人问到TCP/IP协议有哪些原理和有什么作用?

  好的没问题!(我是谁、我在哪、我该怎么办...555...谁来救救我...流下了没技术的眼泪...)

TCP/IP很重要,书到用时方知少,后不后悔当初没弄明白。用的时候欲哭无泪?

接下来作者带你们一起学习一遍

一.概述

  1.分层

      网络协议通常分不同层次进行开发,每一层分别负责不同的通信功能。

  2.TCP/IP通常被认为是一个四层协议系统(为什么是四层)

 

      (1)  应用层:负责处理特定的应用程序细节。

      (2)  运输层:运输层在整个TCP/IP协议中起到了中流砥柱的作用。且在运输层中,TCP和UDP也同样起到了中流砥柱的作用。

      (3)  网络层(IP层):在TCP/IP协议中网络层可以进行网络连接的建立和终止以及IP地址的寻找等功能。 

      (4)  链路层:也被称作数据链路层或网络接口层,通常包括操作系统中的设备驱动程序和计算机中对应的网络接口卡。网络接口层既是传输数据的物理媒介,也可以为网络层提供一条准确无误的线路。协议包括:Telnet、FTP、SMTP 、HTTP、HTTPS等等

     问:那有没有第五层???

     答:emm...有  赶紧洗漱快点睡就有了~

     其实这个看个人理解你非要五层而不是四层,你可以自己将物理层拆出来变成第五层。(硬件接口层)

    

二.干货部分

  1.可靠性

      TCP发送消息文件可靠,UDP不可靠。

为什么TCP就可靠UDP就不可靠,我就要UDP可靠TCP不可靠可不可以...

emmmm...(原谅我又流下了没技术的眼泪...)

  2.IP的作用

      (1)  TCP、UDP都需要根据IP来进行首发文件,TCP、UDP相当于你快递单,IP相当于地址。

  3.TCP和UDP的区别

          

      (1)  使用UDP为什么不可靠

           UDP:用户数据包协议。提供无连接、尽最大努力的数据传输服务(不保证数据传输的可靠性),既然不保证那肯定谈不上可靠一说。

           无连接:不需要建立连接,也不需要释放连接,减少了开销和发送数据的时延。

           尽最大努力的数据传输服务:不保证数据传输的可靠性,没有超时和重传功能。

           面向报文:发送方对应用程序交下来的服务,添加首部后就向下交付给IP层,不合并,也不拆分,保留文本的边界。UDP一次性交付一个完整的报文,因此应用程序一定要选择合适大小的报文,报文太长IP层需要进行分片,太短会导致IP数据包的相对长度过大,效率过低。接收方,去除首部后就交给应用程序。

           不受网络拥堵影响:网络出现的拥塞不会使源主机的发送速率降低。对实时应用非常重要。例如:IP电话、实时视频会议、允许丢失数据但不允许有太大时延(即这些应用可以卡一下,但是要保证其实时性),可能会导致丢包现象发生,可靠性低。

           支持一对一、一对多、多对一、多对多的操作。(稍后会出专门博客讲解,代码已经实现最后测试一下就好)

           首部开销小:只有8个字节,TCP首部需要20个字节。

           发生丢包:UDP不会补发,但是会自动检测是否丢(包)失某些内容,如果有错误就会直接丢包,返回发送失败。

      (2)  使用TCP可靠吗?为什么可靠?

          TCP:用户数据包协议。提供面向连接、保证数据的可靠性。

           面向连接:在使用 TCP 协议之前,必须建立TCP连接,在传送数据完毕之后,必须释放连接。

           TCP连接只能有两个端点:点对点  即一对一。

           TCP提供可靠交付的服务:通过TCP连接传送的数据无差错、不丢失、不重复、并且按序到达

           TCP提供全双工通信:通信双方的应用进程任何时候都可以发送数据。

           TCP协议:一对一。

           TCP 连接:两端都设有发送缓存,接受缓存,用来储存临时通信的数据。发送时,应用程序把数据传送给TCP的缓存,就可以做其他事了。接收时,TCP把收到的数据放入缓存,上层应用程序在合适的时候读取缓存。

           面向字节流:TCP中的流指的是流入到进程或从进程中流出的字节序列。”面向字节流 的含义“ 应用程序和TCP是一次一个数据块(大小不等)。不易发生丢包现象可靠性高(有丢包重发机制)。

      (3)  UDP和TCP的优缺点

           TCP面向连接(如打电话要先拨号建立连接);UDP是无连接的,即发送数据之前不需要建立连接

           TCP提供可靠的服务。也就是说,通过TCP连接传送的数据,无差错,不丢失,不重复,且按序到达;UDP尽最大努力交付,即不保证可靠交付(Tcp通过校验和,重传控制,序号标识,滑动窗口、确认应答实现可靠传输。如丢包时的重发控制,还可以对次序乱掉的分包进行顺序控制)。

           • UDP具有较好的实时性,工作效率比TCP高,适用于对高速传输和实时性有较高的通信或广播通信。  

           • 每一条TCP连接只能是点到点、一对一的;UDP支持一对一,一对多,多对一和多对多的交互通信

           • TCP对系统资源要求较多,UDP对系统资源要求较少。

  4.TCP的三次握手

      (1) TCP状态转移解释(为什么先解释一下呢?你说为什么?废话太多了!NO,因为废话多点才能更好的理解啊~)

         CLOSED  阻塞或关闭状态,表示主机当前没有正在传输或者建立的链接

         LISTEN  监听状态,表示服务器做好准备,等待建立传输链接

         SYN RECV  收到第一次的传输请求,还未进行确认

         SYN SENT  发送完第一个SYN报文,等待收到确认

         ESTABLISHED  链接正常建立之后进入数据传输阶段

         FIN WAIT1  主动发送第一个FIN报文之后进入该状态

         FIN WAIT2  已经收到第一个FIN的确认信号,等待对方发送关闭请求

         TIMED WAIT  完成双向链接关闭,等待分组消失

         CLOSING  双方同时关闭请求,等待对方确认时

         CLOSE WAIT  收到对方的关闭请求并进行确认进入该状态

         LAST ACK  等待最后一次确认关闭的报文

         (为什么不是表格呢?作者不会啊...555......)

      (2) TCP的三次握手

         • TCP作为一种可靠传输控制协议,其核心思想:既要保证数据可靠传输,又要提高传输的效率,而用恰恰可以满足以上两方面的需求!(为什么是恰恰而不是沙土呢,因为...)

         洽洽瓜子吃着就是香~(别误会,我就是打广告的~)爱心提示:吃完多喝水小心舌头疼...
        

         第一次握手:建立连接。客户端发送连接请求报文段,并将syn(标记位)设置为1,Squence Number(数据包序号)(seq)为i,接下来等待服务端确认,客户端进入SYN_SENT状态(请求连接);

         第二次握手:服务端收到客户端的  SYN 报文段,对 SYN 报文段进行确认,设置 acl(确认号)为 i+1(即seq+1 ; 同时自己还要发送 SYN 请求信息,将 SYN 设置为1, seq为 j。服务端将上述所有信息放到 SYN+ACK 报文段中,一并发送给客户端,此时服务器进入 SYN_RECV状态。

         • 第三次握手:客户端收到服务端的 SYN+ACK(确认符) 报文段;然后将 ACK 设置为 j+1,向服务端发送ACK报文段,这个报文段发送完毕后,客户端和服务端都进入ESTABLISHED(连接成功)状态,完成TCP 的三次握手。

         • 没明白怎么办...(其实作者也是这么想的加来加去反正你说怎么连就怎么连呗~)

        

         那就换个说法:第一次握手第一台计算机会发送一个1。第二次握手如果第二台计算机收到然后就会+1返回去说我收到了再发一个1。第三次握手第一台计算机会收到第二台计算机返回的2证明第二台计算机已经收到了,然后再将第二台计算机发的1 加1,意思是说我要开始发数据了。这回应该明白了吧!

         有的小伙伴就说了,嗯...算是明白了,那你的对象半路让别人把手牵走了怎么办???

         兄弟,醒醒吧~ 好好想想,这个对象是哪来的?

      (3) TCP报文格式以及连接对象半路丢失怎么办

         报文格式(可以选读也可以跳过,最好了解一下)

       

         首部有20字节的固定长度(为什么有20字节的固定长度???我也是复制过来的你问我为什么???问就是不会!)

         

          源端口和目的端口:各占2字节,存储源端口号和目的端口

          序号seq:占4字节,表示的范围就是整形的范围[0~2^32]。序号使用在给数据部分每个字节进行编号的,编号方式是mod 2^32 。

          确认号ack:占4字节,范围也是无符号整数的范围。使用在对端传输给我的数据最后一个字节序号,例如A传输给B 101—500,此时B返回的确认号一定是小于等于501的。当B段正确接收数据之后才会返回确认号,换句话说确认号之前的数据已经全部接收。

          数据偏移:占4bit,数据偏移很多人很容易想到是不是表示数据的长度,那就错了。偏移嘛,指的是TCP起始位置到数据部分的起始位置的偏移,也就是TCP首部的长度。

          保留:占6bit,保留字段顾名思义,就是为今后使用,默认置为0。

          紧急URG控制位:占用1bit,URG=1,表示紧急指针有效,此时tcp数据优先传输。相当于生活中的紧急通道,特殊情况时使用。在网络中也会有特殊情况,例如,发送一个很长的程序在远程服务器上运行,此时发现程序有bug,需要中断运行,因此我们从键盘输入Ctrl c,假如不使用紧急数据,需要在缓冲区里排队,都知道是bug了,还要排队,这怕是要出锅啊。此时使用紧急数据传输,不需要排队,直接中断程序是不是更符合我们的预期。需要注意一点是,即使窗口为0时,也可以发送紧急数据。

          如何使用紧急URG控制位,在socket编程中send函数flag参数    

          send(int socket, const void *buffer, size_t length, int flags);

         flags参数传MSG_OOB宏时,表示此时有紧急数据。MSG_OOB是个宏

         确认ACK:占1bit,当ACK=1时生效。TCP有条硬性规定,当建立链接成功后所有传输的数据报文都必须把ACK置为1。

         推送PSH:占1bit,发送方把PSH置为1时 会立即发送该数据包,接收方收到PSH=1的报文会立即处理交付给应用层处理。是不是感觉和URG很像,其实还是有些区别的。


  
  1. //两者相同点:
  2. URG与PSH两者都使用于紧急处理的情况,用来快速传输紧急数据。
  3. //两者不同点
  4. URG置为 1时,对于发送发,“带外数据”与正常情况下应该发送的消息数据一起,封装成数据报发送,省去了在队列中等待的时间。
  5. 在接收方,解析报文后,获取数据之后还是要放在缓存区中,等待满了之后在向上往应用层交付。
  6. PSH置为 1时,对于发送方,表明这些数据不需要等向下发送的缓存区满,立刻封装成报文,发送,省去了等待发送缓存区到达满的状态的时间。
  7. 在接收方,也不需要等接受缓存区满,直接向上交付给应用层。

         复位RST:占1bit,当RST=1时,TCP会主动释放链接,两种情况会用上。TCP出现严重差错时,会主动释放连接,重建链接,传输数据。遇到非法报文或者拒绝连接时会把RST置为1。

         同步SYN:占1bit,同步控制位,用来在传输连接建立时同步传输连接序号。SYN=1时,表示这是一个连接请求或连接确认报文。SYN=1,ACK=0,表明这是一个连接请求数据段,如果对方同意建立连接,则对方会返回一个SYN=1、ACK=1的确认。

         FIN控制位:占1bit,用于释放一个传输连接。FIN=1时,表示数据已全部传输完成,发送端没有数据要传输了,要求释放当前连接,但是接收端仍然可以继续接收还没有接收完的数据。FIN=0,正常传输数据。

         窗口大小:占16bit,2byte,用于表示发送方可以接受的最大数据大小。该窗口是动态变化的,用作流量控制时使用。

         检验和:占16bit,2byte,用于对TCP头部,伪头部,数据三个部分进行校验。

         紧急指针:占16bit,2byte,用于记录紧急数据的末尾在数据段中的位置。当URG=1时,该指针才生效。

         可选项:可选项最长可达40byte,是可选的,可以没有。当可选项不存在时,TCP头部长度为20byte。可选项可以包括窗口缩放选项(Window ScaleOption,WSopt)、MSS(最大数据段大小)选项、SACK(选择性确认)选项、时间戳(Timestamp)选项等。

         数据:TCP数据部分,由应用层应用程序提交的数据。

         这么多记不住怎么办,赶紧点收藏呀~,页面右下角五角星收藏。

      (4) 报文在三次握手过程中丢失怎么办?

        第一次握手丢失(你是故意的吧...)

         第一次:计算机(第一台计算机)发送SYN=1的请求报文,此时第一台计算机进入SYN SENT状态,等待服务器(第二台计算机)确认。


  
  1. //此时如果报文丢失发送不到对端会如何?
  2. 第一台计算机发送报文之后会启动一个定时器,在超时之后未收到服务器端的确认,会再次发送SYN请求,
  3. 每次尝试的时间会是第一次的二倍,如果总的总尝试时间为 75秒,此次建立链接失败。

         第二次:服务器端收到计算机发送的SYN报文(建立链接请求)后,S端必须返回确认号并且同时发送一条SYN报文,此时进入SYN RCVD状态。


  
  1. //为啥要连带发送SYN报文?
  2. TCP是全双工通信,协议规定当收到建立链接请求后必须返回序列号,同时建立本端到对端的通信链接。
  3. 这也叫做捎带应答机制。
  4. //如果第二次报文丢失怎么办?
  5. 在发送完ACK+SYN报文后会启动一个定时器,超时没有收到ACK确认,会再次发送,会进行多次重试。
  6. 超时时间依旧每次翻倍,重试次数可设置。
  7. 修改 /proc/sys/net/ipv4/tcp_synack_retries 的值

         第三次:C端收到S端发的ACK+SYN报文,需要返回一个应答ACK的报文,此时该连接会进入半连接状态的队列,当S端收到ACK后,一条完整的全双工TCP链接建立完成,双方进入ESTABLISHED状态。


  
  1. 这里有个常用攻击手段,攻击者伪造一个SYN请求发送给服务端,服务端响应之后,会收不到C端的ACK确认,
  2. 服务端会不断的重试,默认会重试五次。
  3. 此时服务端会维持这个链接的所有资源,如果有大量这样的请求,服务端的资源会被耗完。
  4. 这就是DOS攻击。
  5. //如果第三次报文丢失怎么办?
  6. S端在发出ACK+SYN报文后会启动一个定时器,在超时触发还没收到ACK就确认是丢失了,会重试一次发送。

      (5) 为什么需要握三次手,两次或者四次可以吗??

         为什么两次不可以?因为计算机和服务器只做两次握手的话只是单向通信,TCP是全双工通信的必须保证可靠性。


  
  1. 1.二次握手失败,C端会重复发送SYN报文,等待对端发送确认报文,S端会保存tcp连接的所有资源,
  2. 大量的这种情况会导致S资源耗尽。
  3. 2.二次握手成功,S收不到ACK会重复发送SYN+ACK报文。
  4. 3.二次握手完以后,双方以为连接建立成功,即可开始通信。假如此时连接并没有真的建立成功,
  5. S端开始发送消息,会造成网络拥堵发生。

        为什么四次不可以?四次其实原则上来说是可以的,就是把第二次的ACK和SYN分两次发送。在理论上是完全可以行得通的,但是TCP本着节约网络网络资源的前提。

        三次握手之后计算机如果继续发送SYN报文,服务端会怎么样???其时这是徒劳的。第三次完成以后链接已经建立,后面无论多少次都是徒劳。

        如果TCP同时建立连接会怎么样???

       

        此时只会建立一条全双工的TCP链接,不是两条。

        • 双方没有CS之分,两端都是同时承担两个角色,客户端和服务器。

  4.TCP的四次挥手

 

      (1) 四次挥手

         第一次挥手:当计算机的应用程序结束数据传输是,会向服务器端发送一个带有FIN附加标记的报文段(FIN表示英文finish),此时计算机端进入FIN_WAIT1状态,计算机端不能在发送数据到服务器端。(我要走了...)

         第二次挥手:服务器端收到FIN报文会响应一个ACK报文,服务器端进入CLOSE_WAIT状态。进入此状态后服务器端把剩余未发送的数据发送到计算机端,计算机端收到服务器端的ACK之后,进入FIN_WAIT2状态。同时继续接受服务器端传输的其他数据包。(好的,你走吧...)

         第三次挥手:服务器端处理完自己待发送的数据之后,也会发送FIN断开链接的请求,服务器端端进入LAST_ACK状态。(你走了吗?)

         第四次挥手:计算机端收到服务器端的断开链接请求后会启动一个定时器,该定时器时长是2MSL(最大段报文生存时间),同时发送最后一次ACK报文。(88,我撤了...断开连接...)


  
  1. //为什么要四次挥手?
  2. TCP是全双工(双向)的通信机制,每个方向必须单独进行关闭。
  3. TCP传输连接关闭的原则如下:
  4. 当一端完成它的数据发送任务后就可以发送一个FIN字段置 1的数据段来终止这个方向的数据发送;
  5. 当另一端收到这个FIN数据段后,必须通知它的应用层 对端已经终止了那个方向的数据传送。

  
  1. //为什么不能用三次握手中捎带应答机制减少一次握手?
  2. 可以是可以但是
  3. TCP是全双工通信的,服务器收到断开链接请求后只是表示计算机端不会传输数据到服务器端了,
  4. 但是并不表示服务器端不传输数据到计算机端。
  5. 如果采用捎带应答,服务器端将无法把剩余的数据传输到计算机端。

  
  1. //为何最后一次ACK之后需要等待2MSL的时间?
  2. MSL:报文段最大生存时间,它是任何报文段被丢弃前在网络内的最长时间
  3. 原因如下:
  4. 保证TCP协议的全双工连接能够可靠关闭
  5. 保证这次连接的重复数据从网络中消失
  6. 第一点: 如果主机 1直接 关闭,由于IP协议的不可靠性或者其他网络原因,导致主机 2没有收到主机 1最后回复的 ACK。那么主机 2就会在超时之后继续发送 FIN,此时由于主机 1已经关闭,就找不到与重发的 FIN 对应的连接。所以,主机 1 不是直接进入 关闭,而是TIME_WAIT 状态。当再次收到 FIN 的时候,能够保证对方收到 ACK ,最后正确关闭连接。
  7. 第二点:如果主机 1直接 关闭,然后又再向主机 2 发起一个新连接,我们不能保证这个新连接与刚才关闭的连接端口是不同的。也就是说有可能新连接和老连接的端口号是相同的。一般来说不会发生什么问题,但还是有特殊情况出现;假设新连接和已经关闭的老连接端口号是一样的,如果前一次连接的某些数据仍然滞留在网络中( Lost Duplicate ),那些延迟数据在建立新连接之后才到达主机 2,由于新连接和老连接的端口号是一样的,TCP 协议就认为哪个延迟的数据时属于新连接的,这样就和真正的新连接的数据包发生混淆了。所以TCP连接要在 TIME_WAIT 状态等待两倍 MSL ,保证本次连接的所有数据都从网络中消失。

  
  1. //为何是2MSL的时间?
  2. 2MSL是报文一个往返的最长时间,假设小于这个时间会发生,ACK丢了,
  3. 但是还没接收到对方重传的FIN我方就重新发送了ACK。

  
  1. //如果已经建立了连接,但是客户端突然出现故障了怎么办?
  2. TCP自己做了保证,TCP默认有个定时器,每次收到客户端的请求后会把定时器设置好,
  3. 通常设置两小时,超过两小时还没收到数据。
  4. 服务端会发送一个探测报文,以后每隔 75秒钟发送一次。若一连发送 10个探测报文仍然没反应,
  5. 服务器就认为客户端出了故障,接着就关闭连接。

  5. 其它协议      

      (1) HTTP长连接

        如果有大量的连接,每次在连接,关闭都要经历三次握手,四次挥手,这显然会造成性能低下。因此。Http 有一种叫做 长连接(keepalive connections) 的机制。它可以在传输数据后仍保持连接,当客户端需要再次获取数据时,直接使用刚刚空闲下来的连接而无需再次握手。

      (2) 其它协议

        

  6. 结语

      •  书山有路勤为径,学海无涯苦作舟。

      •  TCP/IP/UDP介绍已经讲完了,接下来会发布C++、MFC TCP连接的实现,UDP连接已经实现了正在编辑当中两天左右就会发出来。

        我要是之前面试看到这篇文章,我能被面试官问到???

        从此不再会被TCP\IP难倒!

 

 

 

 


转载:https://blog.csdn.net/qq_37529913/article/details/106765916
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场