• 网络基础2(上):http协议、tcp/udp协议


     "逆风让翱翔,更珍贵"


    (一)应用层 

    应用层是我们最常接触到的,编写代码的所在层。往下的传输、网路....由OS管理。

    (1)初始HTTP 

    ①认识URL

    ②urlencode和urldecode


     像 "/ ? :" ......这样的字符, 已经被url当做特殊意义理解了. 因此这些字符不能随意出现.

     
    urlencode/urldecod 修改工具https://tool.chinaz.com/tools/urlencode.aspx

     将需要转码的字符转为16进制,然后从右到左,取4位(不足4位直接处理),每2位做一位,前面加上%,编码成%XY格式。

    urldecode 就是 urlencode的逆过程

    (2)HTTP协议格式 

     (3)HTTP的方法:

    ①GET vs POST请求资源

    get:直接获取网页信息. GET可以带参, URL网址后 “?” 

    POST:对应参数 通过正文传参(不通过URL) 

    可知,由url带参 的传参效率肯定不如 用正文传参更好。

    并且,POST 与  GET在参数的私密性上,POST > GET

    当然,在http / 1.1,时可以支持长链接:

    ②其他方法: 

    方法说明支持的http协议版本
    PUT传输实体主体1.0、1.1
    HEAD获得报文首部1.0、1.1
    DELETE删除文件1.0、1.1
    OPTIONS    询问支持方法1.0、1.1
    TRACE跟踪路径1.1
    CONNECT要求隧道协议连接代理1.1
    LINK               建立资源联系1.0
    UNLINK断开连接关系1.0

    但是最常用的就是,GET 和 POST方法。

    (4)HTTP状态码:

    类别原因
    1xx信息类状态码接收的请求正在处理
    2xx成功状态码请求 正常处理
    3xx重定向状态码需要进行附加操作完成请求
    4xx客户端状态错误服务端无法处理 请求
    5xx服务器错误服务端处理请求 错误

    注:所谓的(3xx)重定向,就是为了更新用户的目标地址!

    (5)其他常见的HTTP_header:

    1.Content-Type: 数据类型(text/html等)。
    2.Content-Length: Body(正文)的长度。

    3.Host: 服务器的IP+端口
    4.User-Agent: 声明用户的操作系统和浏览器版本信息。 

    5.referer: 当前页面是从哪个页面跳转过来的。

    6.location: 搭配3xx状态码使用, 告诉客户端接下来要去哪里访问(重定向)。
    7.Cookie:用于在客户端存储少量信息;
     

    ①理解cookie

    我们在生活中,都有一个常识。登录一个网站,比如说哔哩哔哩、爱奇艺....如果是第一次登录,则需要用户提供自己的账号+密码,但是第二次、三次之后就不再需要了提供了,这是为什么呢?

    所以,本地cookie记录的是用户个人隐私的账号、密码,就一定会存在被盗的风险。

    因此,之后堆cookie值检测的时,引入了session_id 进行了优化

     

     (6)模拟实现HTTP请求(request) 与 响应(response)

    ①建立通信 

    ②连接请求 

    ③链接响应: 

     ③POST 与 GET传参

     

    ④重定向与location 


    (二)传输层 

    (1)认识传输层 

     所谓传输层,指的是数据传输的通信协议。

    最常用的也就是 tcp/udp协议

    ①再谈端口号:

     端口号(Port)唯一标识了,一个主机上的一个进程

     在tcp/udp协议中,用 “源端口号“、“目的端口号”、“源IP”、“目的IP”,“协议号”。识别进程间通信。

    ②端口划分范围 

    我们都知道,端口大小,是一个16位的整型。

    0 - 1023:HTTP, FTP, SSH等这些广为使用的应用层协议, 他们的端口号都是固定的
     

    1024 - 65535: 操作系统动态分配的端口号

    知名端口号:

    ssh服务器:使用22端口
    ftp服务器,:使用21端口
    telnet服务器,:使用23端口
    http服务器,:使用80端口
    https服务器: 使用443端口

    1. 查看端口号
    2. cat /etc/service

    ③netstat:查看网络状态工具(简单介绍) 

    -n:拒绝显示别名,能显示数字的全部转化成数字
    -l:仅列出有在 Listen (监听) 的服务状态

    p:显示建立相关链接的进程名
    t(u):(tcp)仅显示tcp相关选项 / 仅显示udp的相关选项 
    a(all): 显示所有,默认不显示listen

    ④iostate:监控io的负载情况

    -c 只显示cpu相关统计信息(默认是同时显示cpu和磁盘信息)

    -d 只显示磁盘统计信息(默认是同时显示cpu和磁盘信息)

    ....

    当然 还有更多io的指令 

      

    ⑤pidof:获得进程pid 

    通过进程名,可以直接查看它的pid

    两个问题: 

    只需要保证 绑定的port 与 端口是唯一关系就行。 

    (2)UDP协议 

     ①UDP协议格式

    在之前曾经提到过,协议共性的两个特点:

    1.有确立 有效载荷 \ 报头的间隔。  (http中是 空行)

    2.有明确表示 有效载荷交付给上层哪个

     它是如何保证的?

    ·16为UDP长度,表示整个数据报(首部+数据)的最大长度

    ·16位校验和用于 比对数据,出错就 丢弃。

    ②协议共性 与 UDP

    要理解UDP协议的,不得不理解报头C结构体。

     那么,我们知道了报头,拿到了报头的数据,你又怎能保证,一定能发给对端服务器的进程呢??

    原理就是采用一直哈希映射,能够因为拿到 目的端口号port,从而能够快速找到进程!

    ③UDP特点 

    1.无连接: 知道对端的IP和端口号就直接进行传输, 不需要建立连接
    2.不可靠: 没有确认机制, 没有重传机制!如果因为网络故障该段无法发到对方, UDP协议层也不会给应用层返回任何错误信息;
    3.面向数据报:不能够灵活的控制读写数据的次数和数量

    面向数据报:

    应用层交给UDP多长的报文,原样发送,既不拆分,也不合并。

    ④UDP缓冲区 

      udp没有真正意义上的发送缓冲区,调用sendto会直接把数据交给内核,由内核交由网络传输协议。

      udp是有接收缓冲区的,但这个缓冲区不保证 接收数据的有序性。并且一旦缓冲区数据满了,多余的部分会被丢弃!

    udp的socket既能读,也能收,所以也叫做“全双工”。 


     

    (三)TCP协议

    为什么网络传输的数据会存在不可靠的现象?

    当电线足够长,经过的设备越多,任何一个设备出故障,都可能造成网络通信,传输数据的不可靠。 

    ①TCP结构 

    TCP全称为"传输控制协议"。可以看出,TCP主打的是对数据传输的控制。

    源端口号/目的端口号:从哪里来,到哪里去。

    32位序号,32位确认序号:之后会讲

    TCP首部长度:计算这个结构有占多少字节。

    六个标志位:URG ACK RST....之后会细讲

    16位窗口大小:之后会讲 


    ②TCP首部长度 

    (1)TCP协议结构详解

     ①序列 与 确认序列

    双方主机进行通信 

     TCP为每字节数据 都进行了编号(这个理解之后会提到),即称为序列号。

    32位序号:起始序号 + 有效载荷的区域段

           

    32为确认序号:  对应32位序号 + 1 ,表示下一次发送数据的 起始序号 

                            此外:隐含告知,成功接收到的数据量(之后会讲)

    你可能会存在以下的问题

    为什么需要两套序号??一套不就够了吗? 

     同udp不同,udp只有接收缓冲区,发送的任务交由内核部分完成。

    但是tcp有 独立的接收 + 发送缓冲区。

    因此,他们发送数据,也是确认应答的需要<应答机制> 。

    ②16位窗口大小

     在上面刚刚也谈到了,TCP协议有自己独立的缓冲区。

    因此上层应用层不是直接将自己的数据,拿到网络中去 传输,而是把数据拷贝(memcpy\memmove)至TCP的缓冲区中。

    通信有关双方,不是一方向另一方无脑地发送数据。

     因此,接收方就需要把自己的接收能力,告诉发送方,让发送方适应自己的接收能力。从而降低出现数据传输不一致性的可能。

    ③紧急指针

    所谓紧急指针,就是保存着紧急数据的地址。

    因为序号的缘故,TCP读取数据是有序的! 那么如果出现重要的数据,需要被先读取,就可以使用紧急指针。

    公式:紧急数据字节号(urgSeq)=TCP报文序号(seq)+紧急指针(urgpoint)−1;

       所以,紧急指针存的是 TCP报头,到数据段的 偏移量!

    ④六个标志位 

    各个标志位,在不同的场景下,运用不同!

    URG:紧急指针是否有效。

    ACK:确认号是否有效。

    PSH:提醒赶快把接收缓冲区里的数据 拿走。

    RST:重新建立链接,重传数据。

    SYN:请求连接。(同步报文段)

    FIN:通知对端,本段要关闭。(结束报文段) 


    (2)可靠性保障机制

    对于UDP而言,发布出去的数据,或者数据打满了接收缓冲区,多余的部分直接进行丢弃。很显然,这是不能被容忍的。

    在我们日常生活中,如何保证自己的消息得到传播是可靠的? 答案就是,当我们对一个人说一句话,

    那个人或是点头,或是也回话,那么我们就认为,我传输给他的消息就是可靠的。

    这也就是,应答机制的雏形。

    ①确认应答机制

    注:

    因为,在应用层以下都是属于内核级别的,所以socket通信渠道的建立 都是由OS来完成。

    与系统调用接口的联系:

    发送三次握手---->connet  建立连接----->accept(完成了三次握手)   

    ②超时重传机制 

    当发生如下的

    数据在传输的过程中,迟迟收不到应答(ACK), 或者收到同样的ACK应答。

    那么对于这种情况应该怎样处理?

    需要进行超时重传

    最理想的情况下, 找到一个最小的时间, 保证 "确认应答一定能在这个时间内返回".

    但是这个时间的长短, 随着网络环境的不同, 是有差异的。

    对于超时的时长,既不能太长,也不能太短!

    Linux中(BSD Unix和Windows也是如此),

    超时以500ms为一个单位进行控制, 每次判定超时重发的超时时间都是500ms的整数倍.

     超时重传依据:

    对于client而言,认为ACK发出,那么连接就已经建立。

    但对于server而言,收到ACK,连接才建立。

    因此,发送方没收到ACK应答,达到一定时间,就需要 再一次向对方申请(RST)重传,

    建立新连接。

    ③流量控制

    TCP的处理速度,严格上来说是由接收方决定! 

    因此TCP支持根据 接收端的处理能力, 来决定发送端的发送速度.

    这个机制就叫做流量控制(Flow Control);

    依托: syn进行 窗口大小的交互。

    ④连接管理机制

     为什么要三次握手?而不是四次,五次??

    如何理解四次挥手?

     如何理解只关闭client端 close(fd)?

    为什么主动断开连接的一方不能立即进入CLOSED?

    理解TIME_WAIT状态

    所以,断开链接不是 一定会断开!

    注:TCP保证的是数据通信之中,但不保证建立 、 断开。

    等待时长: 

    bind失败问题:

    因为 进行主动断开链接的一方,一定会进入TIME_WAIT 状态。导致连接并没有被完全释放。因此不能bind端口。

    1. //解决bind失败的 端口
    2. int setsockopt(int sockfd, int level, int optname,
    3. const void *optval, socklen_t optlen);

     测试TIME_WAIT状态:

    ⑤拥塞控制:

    我们分别对 发送端,接收端 进了考虑。看是否 接收端的接受能力(窗口大小-->流量控制)、发送端的发送能力(滑动窗口),但如果问题不是出现在 双方,而是出现在网络通道上呢??

    在大型的局域网中,不止有一台主机正在进行通信。可能当前的网络状态就已经比较拥堵. 在不清楚当前网络状态下, 贸然发送大量的数据,是很有可能引起雪上加霜的。

    所以,在考虑传输的时候,不仅仅需要考虑 对端的接收能力,更需要考虑网络状况的承受能力。

    TCP引入了 “慢启动”的机制; 指数增长(2^n)

    ①慢慢恢复通信速度。

    ②确认少量时,会不会依旧丢包

    ③引入慢启动 域值


     (3)TCP效率优化

    ①滑动窗口 

    对每一个发送的数据段, 都要给一个ACK确认应答. 收到ACK后再发送下一个数据段。
    这样做有一个比较大的缺点, 就是性能较差. 尤其是数据往返的时间较长的时候,效率必然很低。

    因此,我们连续给对方发送多条数据,优化性能。

    所以,滑动窗口是在发送方内部的。 

     滑动窗口大小 ==MIN(接收端的窗口大小,拥塞窗口)

    因为现在并没有讲拥塞窗口。 就可近似理解 滑动窗口大小 == TCP报头带的窗口大小

     

     窗口大小 vs 滑动窗口:
     

            窗口大小:接收缓冲区能够接收的大小。

            滑动窗口:发送缓冲区,一段限制的区域,不用收到ACK,就可发送数据。 

    滑动窗口的特殊情况下的快传机制

     (1)ACK在响应的途中丢包,但是数据包传达。

    (2)但如果不是ACK响应丢包,而是数据传达丢包

     快重传 vs 超时重传

            快重传是一种机制,收到连续3次同样的ACK响应。

            超时重传是一种策略,是一种重传机制的保底。

     

    ②延迟应答

    ③捎带应答

     

     数据一并传输过去。

    TCP小结:

    可靠性:校验和、序列号(普通+确认)、应答机制、重发机制(超时、快重传)、流量控制、拥塞控制

    优化性能:滑动窗口 、 延迟应答 、 捎带应答   ----->策略性协议!


     (四)TCP协议的其他问题

    (1)面向字节流

    UDP是面向数据报,应用层接收多少数据,就发送多少数据。 不能灵活控制 接收+发送

    TCP是面向字节流,灵活控制数据的写入 和 接收。不受限制

    (2)粘包问题 

     所谓粘包问题,指的就是,有效载荷 与 报头不能有效分离!

    为什么TCP有粘包问题?

    但是,UDP就不会存在粘包问题,因为它的结构是 定长报文,很容易鉴别。

    本质上就是TCP是面向字节流,基于TCP的应用层不能很好的 分别报头 和 有效载荷的界限。 

    如何解决? (区别 报文 和 有效载荷)

    ①定长报头

    ②特殊字符

    ③字描述+定长(特殊字符) 

    (3)TCP异常问题

    我们知道 进程不管是终止 还是机器重启,(sock)文件描述符的生命周期是随进程的。所以并无大碍。

    但,如果是网络出现故障,发送端已经断开了。但此时 接收端以为仍在链接,当接收端进行写入操作时,无响应后,会进行reset。

    即使没有写入操作, TCP内置了一个“保活定时器”,一种心跳机制 ,会定期询问对方。如果对方不在,也就会立即释放连接。

    (4)listen的第二个参数

    这个参数,记录是 established(全连接) + 1。

    Linux协议栈 会为tcp链接管理维护两个队列:


    1.半链接队列(用来保存SYN_SENT \ SYN_RECV请求) ==处于半连接状态

    2.全连接队列(acceptd队列)(用来保存established状态) --> == listen_back+1

    为什么需要维护这个链接队列?

     

    在系统角度:
    维护链接队列本质就是为了,提高满载性能。提高工作效率。

    太长队列,OS维护成本太高,并且被暂时不需要的队列 占用大量资源。 


    总结

    ①http 协议格式 和 http POST GET方法区别 http状态码 cookie理解

    ②UDP协议格式 UDP特点 

    ③TCP协议格式 TCP特点 

    ④ TCP可靠性:

    校验和、序列号(普通+确认)、应答机制、重发机制(超时、快重传)、流量控制、拥塞控制

    ⑤TCP性能:

    滑动窗口 、 延迟应答 、 捎带应答

    ⑥TCP粘包 解决,listen 第二个参数理解


    本篇到此结束 感谢您的阅读

    祝你好运~

  • 相关阅读:
    java毕业设计财务信息管理mybatis+源码+调试部署+系统+数据库+lw
    爱数SMART 2022峰会开启,分享数据战略与建设数据驱动型组织方法论
    GAN Step By Step -- Step3 DCGAN
    永磁同步电机谐波抑制算法(7)——基于自适应陷波(adaptive notch filter,ANF)的精确谐波电流抑制策略
    蓝牙耳机哪个牌子性价比高?千元内真无线耳机推荐
    Show Me the Code之MXNet网络模型(三)
    PS文字创建工作路径矢量化后变细,导出的svg也变细的解决方案
    浅议飞机状态监控
    4. 运行Openocd
    C#中AutoResetEvent 和 ManualResetEvent 的使用总结
  • 原文地址:https://blog.csdn.net/RNGWGzZs/article/details/126535663