网络基础(四)

网络基础(四)

传输层协议—TCP协议和UDP协议
  • 传输层负责端与端(端可以理解为端口,进一步理解就是端口)之间的传输(也就是说,传输层是负责端口与端口之间的传输的),不论是传输层中的UDP协议还是TCP协议,都是负责端口和端口之间的数据传输,也就是说传输层只负责端口,不负责ip(ip是网络层在负责的),传输层重视的是端口,一个是源端口,一个是目的端口

  • 传输层并不在乎ip地址,只在乎端口和端口之间的传输

端口的划分
  • 端口的范围:0~2^16(端口其实就是一个无符号的16位的整数)

  • 知名端口: 0~1023,**比如说http:80 https:443 ssh:22 ftp:21 telnet:23 **

  • 但是并不是说非知名端口就可以随意使用了,还要知道一些常用软件在使用的端口,比如说mysql的3306端口,oracle的1521端口

网络数据在传输过程当中的五元组信息:
  • 任何一个需要在网络当中传输的数据,都要去具备五元组信息,否则网路就不会转发,缺少任何一个东西都无法进行数据的发送

  • 那么为什么不满足五元组信息,网路就不给转发了呢,因为在网络中我们从源主机到目标主机的时候,这个时候,数据的流向是从左边的机器流向右边的机器的,然后是需要具备五元组信息的,这样的一个五元组信息是为了数据在网络当中可以标识他想要取到的地方

  • 源端口,标识数据从源主机的哪个进程提交给协议栈的,协议栈其实就是网络协议栈,因为网络协议栈可以替我们进行一个转发的操作,源端口的引申含义是目的主机回复消息的时候,要给哪个端口回复消息

  • 目的端口:表示数据要到达目标主机的哪一个进程,因为一个端口只能被一个进程所绑定

  • 源端口和目的端口是在传输层,源ip和目的ip在网络层,也就是说端口在传输层,ip地址在网路层

  • 注意:一个端口只能被一个进程所绑定
    在这里插入图片描述

  • 源端口

  • 目的端口

  • 源ip

  • 目的ip

  • 协议

UDP协议
  • UDP的三大特点:无连接,不可靠,面向数据报

  • 无连接指的是—是指再给对方发送消息的时候,不要建立连接,只要知道对方的ip地址以及侦听端口就可以直接进行发送的操作了

  • 不可靠指的是—因为现在是无连接的,所以对端有没有在侦听,其实我也是不知道的,那么对于UDP消息的发送方来说是不关心消息接收方是否工作正常的,对于发送方而言,只关心是否发送成功了数据(发送方只关心自己调用sendto函数是否成功),不关心对端是否成功接收到了数据

  • 面向数据报—需要结合UDP缓冲区来分析,分为发送和接收,应用层给传输层的UDP协议提交数据的时候,应用层的数据会被临时写道UDP协议的发送缓冲区当中,此时,在缓冲区当中打上UDP的报头之后,就递交网络层

  • UDP在接收到UDP数据之后,是整条整条给应用层进行传递的,假如说发送方第一次发送了ABC,第二次发送了123,第三次发送了aaa,对于UDP而言,他是把一整条数据直接都传递给了应用层,不允许说一次性只允许接收一个字节之类的问题,而是讲UDP的整个数据传递给应用层(不具有面向字节流的特点)

UDP协议报头字段的含义

在这里插入图片描述

  • 打开第一个之后,会看到一个结构体
    在这里插入图片描述

  • 协议报头结构体所含的内容如下所示:

  • 就是说你递交的UDP数据到达了我的传输层之后,UDP就会给你所传递过来的数据前面加上下面的这个结构体

  • 第一个叫做源端口,第二个叫做目的端口,第三个叫做数据长度(指的是UDP的数据长度),第四个是校验和—所以就证明了UDP头部其实占有8个字节

  • 源端口和目的端口表示的是数据从哪里来以及数据要去向哪里

  • 数据长度的类型是无符号16位的整数,也就是说UDP数据包最大能表示的范围是65535
    在这里插入图片描述
    在这里插入图片描述

  • 那么既然说了udp数据报长度最大是65535个字节,那么其实就也引申出来了一个问题,如果应用层提交给传输层udp协议的数据超过了65535字节怎么办?----首先需要坚定UDP协议的最大长度是不变的,如果要传输一个超过udp最大长度的数据,应该怎么办呢?—我们能够想到的一个方法其实就是分块传输

  • 在应用层自定制协议,将数据在应用层分割成为满足udp传输的小块,再使用udp协议进行传输,但是现在又带来了一个新的问题,因为udp是面向数据报的,也就是意味着udp是整条数据来进行收发的,那么如何再接收方的应用层表示若干个udp数据是一个应用层数据包呢

  • 假设下图中的两个块都超过了udp最大传输范围,那么既然超过了udp的最大表示范围,就是不能把这个数据直接传输给传输层的udp,因为udp所能接收的最大范围就是65536(uint16_t),也就是说,超过长度的不能直接递交数据

  • 那么,他既然超过了最大的范围,我现在就要对数据进行分片的操作
    在这里插入图片描述
    在这里插入图片描述

  • 在应用层的视角当中,需要传输的数据被分成了不同的小块,本质上这些小块组合在一起,就是我们所要传输的内容,但是在传输层udp协议的视角中,应用层提交的小块数据,就是一个完整的udp数据包

  • 那么接收方的应用层在接收到4个小的数据包之后怎么确定他就是发送方给我发送过来的一个完整的数据呢?

  • 我们所能想到的方式其实就是可以给出一个相同的id来进行标识
    在这里插入图片描述

  • 但是给出同样的标识其实还是存在有问题的,就比如说顺序问题其实就是一个很大的问题,当识别到了id一样的时候,这个时候就需要来进行组合的操作,但是组合的顺序如何来确定的,就会引起一系列的问题

  • 那么,我们又可以想到,在打上了id之后,还可以加上一个偏移量,这样子其实就可以确定顺序了
    在这里插入图片描述

  • 校验和

  • 校验和本质是,其实就是接收方用来校验udp数据在传输过程当中是否失真其实也就是在验证传过来的数据和传送数据的那一方想要发送过来的数据是否是一样的,那么就会出现两种结果,一种是udp数据失真,另一种情况是udp数据没有失真,假如说udp数据失真了,那么发送方的udp数据就和接收方接收到的udp数据不一致,那么如何处理呢? 处理的方式其实就是接收方的传输层,就不会将失真的数据提交给应用层了,直接丢弃了;假如说udp数据没有失真的话,那么就是正常的,是可以直接交给应用层的

校验和的计算方式(了解)

在这里插入图片描述
在这里插入图片描述

UDP缓冲区
  • udp缓冲区是整条数据接收和发送的

  • 对于udp的发送而言,是具有udp的发送缓冲区的,只不过在发送区打上UDP协议的报头之后就直接递交个给网络层了

  • 对于UDP的接收而言,是有UDP的接收缓冲区的,只不过是整条UDP数据提交给应用层的,UDP是不保证UDP数据包时可靠并且有序到达对端的(也就是说其实UDP是存在有丢包问题的)

  • UDP在数据传输过程中是有可能导致丢包问题的

UDP的应用
  • DHCP协议:动态主机分配协议,其实直白一点来说,其实就是谁上网,给谁分配ip,不上网的话,就不会分配ip,为什么会这样呢?其实还是因为本质上ipv4版本的ip地址枯竭的问题,也就是说ipv4版本的ip地址时不够用的,那么换句话来说,可不可以使用ip来作为一台机器的唯一的标识呢?—其实是不可以的,因为现在的ip其实是动态分配的,它可以分配给这台电脑,当然,他也是可以分配给另外一台电脑的,所以ip其实是动态变化的,但是MAC地址是可以的(本质上是由于MAC地址是全球唯一的)

  • DNS协议—也就是域名解析协议,作用其实就是将域名转换为ip地址,而使用的协议其实就是udp协议

TCP协议
  • tcp协议的特性:面向连接,可靠传输,面向字节流

  • 面向连接是指:tcp连接的本质,是在建立连接的三次握手时期,通信双方会协商很多连接当中的参数,比如说MSS,包序号等,对于tcp来说,不建立连接就不能够进行通信;以及对于tcp来说,建立连接的过程是在内核当中完成的,程序员自身只需要调用accept函数,去获取已经完成三次握手的来进行连接,服务端调用accept函数来接收连接

  • 从连接建立的的角度,我们需要讨论三次握手以及四次挥手,不论是三次握手还是说是四次挥手,我们在分析连接的时候,都需要从三个方面来进行分析:(1)双方连接状态—我们在进行三次握手的时候,实际上是会存在有很多中间状态的,这些中间状态我们是需要对其进行了解的(2)连接数据包名称----也就是说我发了一个什么样子的数据包,这个和数据包的名称是什么,这个数据包的作用是什么(3)包序管理—我们是如何进行序号管理的

三次握手(重!)
  • 在建立连接之前,客户端和服务端都需要做一些基础的工作,服务端所要做的工作就是创建套接字,绑定地址信息,监听;客户端所要做的事情其实就是创建套接字,发起连接,至此,客户端和服务都安所要作的准备工作其实就是完成了的

  • 当客户端调用了connect接口发起连接之后发起连接之后进入到三次握手的阶段他就会向服务端发送一个数据包,这个数据包的名称叫做SYN,SYN属于连接请求,客户端发完SYN数据包之后,他自己的状态会变成SYN_SENT状态,服务端接收到SYN数据包之后,服务端会变成SYN_RCVD状态,并且给客户端回复了一个SYN+ACK状态的数据包,ACK叫做确认数据包,也就是说发送回去一个SYN+ACK就是意思告诉客户端,你刚才给我所发送给的SYN这个数据包我是收到了的,然后客户端收到之后,客户端的状态会变更为ESTABLISHED,也就是说连接建立了,此时,对于客户端来说,客户端认为我们的连接已经成功建立了,但是此时,服务端还是处于一个SYN_RCVD状态,所以服务端认为连接还是没有建立成功的,然后这个时候没客户端还会给服务端返回回去一个数据包这个数据包的名称叫做ACK,这个数据包的含义其实是就是客户端要告诉服务端,你刚才给我发送的SYN+ACK数据包我是收到了的,然后这个时候,服务端收到了ACK这个数据包之后他的状态就变成了ESTABLISHED状态,然后这个时候连接就建立了

  • 因为三次握手这个过程其实是在内核中完成的,那么我们现在要去建立连接的话,其实还是需要一个accept的才可以的,当accept接收完毕之后,客户端和服务端就可以正常的进行收发数据了,在正常接收和发送数据 的这个过程当中,需要注意的一点其实就是:连接一旦建立,连接双方都可以先给对方发送数据
    在这里插入图片描述
    在这里插入图片描述

  • 三次握手是在内核中完成的,和程序员是没有任何的关系的,一旦客户端发起连接,就要进行三次握手的阶段, 三次握手就是由内核完成的,由内核完成的换句话说就是由网络协议栈的tcp协议完成的

  • 下面是TCP三次握手的数据包,source是指数据是从哪里发送过来的,Dest是指数据要发送到那里去,分别为源ip和目的ip,所使用的协议是TCP协议,数据长度是80,源端口和目的端口,目的端口为19999

  • SYN后面的一系列的东西其实就是我们在协商的内容
    在这里插入图片描述

  • 因为私网是不能直接访问到互联网的,而是需要通过公网ip来访问互联网,私网ip,在不同的局域网当中可以进行复用,正是因为私网不能直接访问互联网,所以需要NAT服务器把我们的私网转换成公网,从而进行访问互联网的操作,如下图所示,下图的过程其实也同样是一个可逆的过程
    在这里插入图片描述

  • 本质上而言,对于我们的TCP数据包而言,由两个部分组成,一部分是TCP协议包头部分+应用层递交给TCP协议的数据

  • 发起连接的时候,首先需要调用connect函数,调用connect函数之后,就需要去进行三次握手的阶段了

在这里插入图片描述

  • seq是序号,ack是他的确认序号
    在这里插入图片描述
三次握手包序管理
  • TCP的包头字段中是由序号这个内容的
    在这里插入图片描述

  • 那么由下图,其实是可以看到由两个seq=0的,那么就需要来理解一下为什么是由两个seq=0呢?

  • 之所以有两个,其实是因为TCP连接中维护了两套序号,一套是客户端在维护,一套是服务端在维护
    在这里插入图片描述

  • 那么为什么服务端要给客户端同时发送会去一个ACK=1呢?因为,其实ACK=1本质上这是一个确认序号,对于服务端而言,确认序号是在告诉客户端自己期望客户端给自己发送的下一个序号到底是什么,其实这个ACK本质上也是在确认客户端发送过来的SYN序号

  • 既然服务端都告诉客户端我期望客户端下一次给我发送的是1号序号的数据包,则说明0号序号的数据包服务端其实是已经接收到了的

  • 客户端给服务端发送了一个SYN数据包,这个数据包消耗了客户端维护的一个序号,叫做seq0号序号,这个时候到达了对端服务端之后,服务端是需要告诉客户端我是否收到了刚刚你所给我发送的数据包,那么我这个时候确认,其实不是在确认说我收到了你0号序号这个数据包,而是我要告诉你我期望收到的下一个数据包,如果我期望你下一次给我发送的序号是大于你给我发送过来的序号的话,那么就证明之前的所有的序号,我其实都收到了

  • 第三次的seq=1其实也是在消耗客户端的序号
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

  • 图解如下所示:
    在这里插入图片描述

  • 问什么PUSH的东西中seq是从1开始的呢?从这里就可以得出一个结论其实就是纯的ACK数据包是不会消耗序号的

  • 那么在服务端给客户端回消息的时候,回复的是12号序号呢?其实隐含的含义就是服务端已经接受了12号序号之前的所有的内容了,其实我们在发送数据的时候,数据中的每一个字节他其实都是有一个序号的编号的,也就是说我们呢所发送过去的数据其实是有11个字节的,11个字节的内容是从1号序号开始的,从1号序号到11号序号的,所以PUSH的seq序号叫做起始序号

  • PUSH的时候,ACK都等于1的意思是,期望你下一次给我发送的序号是从1号序号开始的

  • 客户端给服务端发送消息在这里插入图片描述

  • 服务端给客户端发送消息
    在这里插入图片描述
    在这里插入图片描述

总结
  • 三次握手当中,连接双方是在协商各自维护的序号的起始位置
  • SYN(seq=0),这一步骤是有两层含义的,第一层是客户端想要和服务端建立连接,第二层含义是客户端告诉服务端,自己维护的序号的其实位置是0
  • SYN+ACK(seq=0,ack=1),引申的含义是,首先服务端告诉客户端,想要和客户端建立连接,第二是服务端告诉客户端,自己维护的序号也是从0开始的(当然,这个不一定就一定是要从0开始),第三,服务端告诉客户端,期望客户端在发送下一条数据的时候,从1号数据开始发送
  • 纯ACK数据包不消耗序号
    在这里插入图片描述
    在这里插入图片描述
四次挥手
  • 当我们通信双方发送数据完毕的时候,我们现在要去断开连接了,我们就需要进行四次挥手的过程了
  • 连接双方的任意一方都可以主动断开连接,断开连接的时候使用的是close接口
  • 假设,现在客户端要来先断开连接,他断开连接的时候,会向服务端发送FIN包,当他把这个包发出去的时候,他的状态就会变成ESTABLISHED状态变成FIN_WAIT_1状态,当服务端接收到这个包之后,服务端的状态就会从ESTABLISHED状态变为CLOSE_WAIT状态,同时他会给客户端发送一个ACK,这个ACK的意思就是说我服务端接收到了你客户端断开连接的请求,然后这个时候,客户端的状态就会从FIN_WAIT_1的状态变成FIN_WAIT_2的状态,然后这个时候其实四次挥手的过程已经完成一半了,然后服务端会给客户端主动断开连接,断开连接的时候,也给客户端发送了一个FIN,然后客户端的状态变成了LAST_ACK的状态,当客户端接收到FIN包文之后他的状态就会变成TIME_WAIT,然后客户端回个服务端发送一个ACK,说他收到了客户端给他发送给的FIN报文,是用来确认的,当服务端接收到了ACK这个东西之后他的状态会从LAST_ACK状态变为CLOSED状态
  • 但是由上述的整个过程来看,我们主动发起断开请求的客户端,他的状态并没有变成CLOSED状态,他还需要等到2MSL的时间,等待了这些时间之后,他的状态就会变回到CLOSED状态
    在这里插入图片描述
    在这里插入图片描述
  • 那么问题又来了,什么是MSL呢?—MSL其实就是发送方认为发送出去的报文最大存活的时间,也就意味着,假设现在服务端给客户端发送一个FIN报文,那么服务端会认为这个FIN保存最多可以存活的时间是MSL时间,如果在这个时间内我还收不到这个ACK的话,接下来就需要去想办法,想的办法其实就是要么是重传,就是说我要给你重新传递一个FIN报文
  • 假设服务端先断开
    在这里插入图片描述
  • 连接断开的请求,可以是客户端先发起,也可以是服务端先发起
如果有一方突然断电的话,会发生什么样的现象

在这里插入图片描述

包序管理
  • 对于TCP连接双方而言,连接双方各维护一套序号,在三次握手期间,双方协商各自的序号的起始位置
  • 三次握手当中,双方的序号的其实位置不一定是从0开始的,可以从任意一个位置开始,后续在传输数据的时候,以协商的序号为基点
  • 纯ACK数据包是不消耗序号的,因为TCP的确认应答是按照序号进行确认的
    在这里插入图片描述
  • 确认序号的计算:当接收方收到一个TCP报文的时候,需要计算一个确认序号,给发送方一个确认;确认序号:发送方发送的数据的起始序号+[数据长度],如果没有数据长度的话,加1起始就可以了(也就是SYN),如果有数据长度的话,确认序号=发送方发送的数据+数据长度(也就是PSH)
四次挥手当中的2MSL的含义以及其必要性
  • 下面给出四次挥手的一种异常情况,就是说如果服务端给客户端发送的FIN报文在网络中丢失的话,也就是说FIN报文没有到达客户端,那么客户端的状态起始还是FIN_WAIT_2,对于服务端而言,他的状态其实还是LAST_ACK的状态,她在等待FIN报文的确认,但是她既然丢掉了,那么其客户端其实是不知道服务端发送了FIN这个报文的,所以说对于客户端的意义其实不大,但是对于服务端而言,意义还是很大的,服务端没有等到FIN报文在限定时间内的回复,等超过这段限定时间之后,服务端就会重传这个报文,那么可以继续正常的进行下面的操作了
  • 也就是说,如果FIN报文丢失了,服务端会进行超时重传
    在这里插入图片描述
    在这里插入图片描述
  • 假如说,是下面的这种情况,FIN报文已经顺利的到达了客户端了,但是客户端回复的ACK丢掉了
  • ACK丢失对于客户端而言,客户端还是处于TIME_WAIT的状态,并且在等到2MSL的时间(之所以等待这个时间是为了把自己的状态变成CLOSED的状态)
  • ACK丢掉对于服务端而言,服务端不清楚FIN报文是否到达了客户端,因为毕竟只有服务端收到了ACK之后才知道FIN报文已经到达了,在服务端发送FIN报文之后,就会开启超时重传机制
  • MSL其实就是报文最大生成时间,也就是在网络中的数据包理论上的最大生存时间
    在这里插入图片描述
  • 那么为什么要等待2MSL的时间呢?—对于ACK来说他其实是由一个最大报文生存时间的,也就是客户端认为ACK他是有一个最大的生存时间的
    在这里插入图片描述
但是TIME_WAIT状态会带来一个问题—TIME_WAIT状态会导致服务端无法快速启动的问题

在这里插入图片描述

  • 那么其实针对上述的问题,也是有解决方案的
  • 但是重用端口也并不是说一个端口可以被多个进程所使用
    在这里插入图片描述
TCP报文头部

在这里插入图片描述

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值