文章目录

  • 一、应用层
    • HTTP:超文本传输协议
      • URL
      • urlencode和urldecode
      • HTTP的基本特征:
      • HTTP协议的整体结构
      • fiddler
      • HTTP 常见Header
        • Cookie
        • session
      • HTTP/HTTPS
      • 长连接与短连接
  • 二、运输层
    • UDP
      • UDP协议端格式
    • TCP
      • TCP协议端格式
      • 超时重传
      • 连接(三次握手,四次挥手)
      • 滑动窗口
      • 拥塞控制
      • 延迟应答
      • listen的第二个参数

一、应用层

我们之前所写的程序都是在应用层。

协议是一种 “约定”。如果我们要传输一些"结构化的数据"怎么办呢?

  • 网络版计算器

HTTP:超文本传输协议

URL

我们平时俗称的“网址”。

urlencode和urldecode

当我们想向服务器提供某些关键字时,倘若该关键字本身内部包含了特殊符号,我们需要对该特殊符号做转化,这个转化的过程叫做encode。当到了服务器端,想要把已经转化的字符做解释,解释的过程叫做decode

HTTP的基本特征:

1、无连接:HTTP是建立在TCP之上的,它不关心TCP通信相关的所有的细节。它的无连接体现在,一旦TCP建立连接成功,HTTP直接向对方发送HTTP request即可,不需要HTTP在应用层建立连接。
2、无状态:HTTP是给用户用的,它并不会记录用户的任何信息,只是进行request、response。记录基本信息的技术是cookie 和 session,并不是HTTP。
3、简单快速:基于短连接(客户端请求,服务器响应,服务器断开连接,一来一回)进行文本(html,img,css,js等多媒体资源)传输。

HTTP协议的整体结构


任何协议必须解决两个问题:
1、报头和有效载荷分离
2、决定自己的有效载荷要交付给上层的哪层协议

HTTP在应用层,已经没有上层了,因此不需要解决交付问题。

而空行已经解决了报头和有效载荷的分离,那么request和request之间怎么区分?
请求报头里有content-length:value,具体的一种key:value。value表示的是空行之后多少个字节是正文部分。

  • 当http请求发送到服务端后,服务器端怎么完整的把这个请求读上来?

发送端是按行发送,那么读取端也会一行一行的读。当读到空行时,认为把协议报头读完了。有效载荷从空行之后开始读,在请求包头中包含了请求正文的字节(Content-Length)。

  • 客户端怎么完整的接收这个响应?
    第一行是响应行,带有换行符,可以完整读出。然后读到空行,报头就读完了。空行之后开始读响应正文,响应报头中包含了响应正文的字节数,就能知道了正文有多长。

fiddler

fiddler抓包原理:

没有fiddler,我们在发起请求时,是浏览器直接构建http请求,通过网络转发给服务器。服务器再把请求转回,浏览器再拿到这个请求。

运行fiddler之后,浏览器的请求不会直接发到网络,而是先把请求发送给fiddler,它拿到请求后把请求推送到网络中。当收到响应时,网络先把响应给fiddler,然后fiddler再交给浏览器。
它承担的角色叫做“代理”,请求->代理->网络,这个过程叫做正向代理。

fiddler能抓包是因为,所有发给网络的请求都要先发给fiddler。

获得http响应的方案也可以在Linux中实现:

ping -c1 www.baidu.com
telnet www.baidu.com 80
GET / HTPP/1.1

GET方法与POST方法的区别
在都传参的情况下,GET通过URL,POST通过正文传参。

POST比GET更私密,POST方法传参并不会回显到浏览器的URL当中,也就意味着它并不会把数据显示到别人的眼中,但它也是要以正文的方式传上去,除非对数据进行加密,否则没有安全性可言。

URL的长度是有上限的。而理论上,正文部分是没有长度限制的。
GET通过URL传参,参数长度受限,而POST可以无限,传更多参数。

HTTP 常见Header

这里的header对应的是请求或响应中的请求报头和响应报头。

Cookie

用于在客户端存储少量信息,通常用于实现会话(session)的功能。

我们知道,HTTP本身是无状态的,但HTTP是给用户用的,如果它是无状态,那么给用户会带来极差的体验——每一次想访问受限资源,都得重新登录认证。
但我们在日常生活中,从来没有遇到过这种情况,因为存在一项cookie技术。

当第一次登录时,客户端在cookie字段向服务器上传了name和password,和服务器里注册过的号进行对比。

服务器端在set-cookie字段带上password和name写回客户端,给予客户端响应。
这个账号信息在浏览器内就以cookie的形式被保存了。

cookie本质是浏览器中的一个文件。也就是浏览器的安装目录里有一个文件,文件里面放的就是cookie信息。自此,在特定的时间段内,每一次浏览器向服务器发起请求时,会自动在自己的HTTP请求中自动包含上字段cookie:name = xxx&& password = xxx,服务器在收到HTTP请求时,会自动分析它上传上来的cookie字段,自动对其认证。
所以,当用户再次访问某次网站时也就不用进行所谓的二次登录。

文件分为两种

  • 内存级(浏览器不关闭,认证就还在;如果关闭了,就需要再次登录)
  • 硬盘级(当浏览器访问某种资源时,关闭后再次打开,也不需要二次登录)

我们把账号密码保存到cookie,cookie并不是很安全,别人可以分析存放在本地的cookie并进行cookie欺骗,就会有危险。此时我们引入了解决方案:session。

session

有了session之后,服务器并不直接给客户端set-cookie写内容,而是在服务器给该用户生成一个sid(全服务器内唯一一个序列号,身份标识)。服务器把这个sid以及登录情况统一写到session文件中,然后,给客户端返回时,不返回set-cookie里写用户密码,只返回sid=xxx,然后客户端把sid保存到cookie文件中
当再次向服务器发起请求时,把只包含sid的cookie中上传给服务器,服务器通过sid找到对应的session文件,获取状态。

总结:
1、单单使用cookie,敏感信息是保存在客户端本地的。而使用session时,敏感信息都保存在服务器。
2、cookie里的内容从账号密码变成了sid,如果发生意外,对方也只能拿到sid,也就是说并不知道这个sid是对应的哪个网站,更安全些。
敏感信息在服务器里放置,因此使用cookie+session安全级别相对更高。

HTTP/HTTPS

HTTP对应的端口号80。
HTTPS:在传输层和应用层又新增了一层安全层,对应的端口号叫做443。


SSL/TLS 会对数据进行加密解密,一般有两种方式。

  • 对称加密

  • 非对称加密

可是,https协议对数据进行加密传输,但也会不可避免的出现“中间人”,对传输的数据进行监听。

因此,我们需要解决两个问题:

  • 如何防止信息被中间篡改?

  • 怎么知道此时访问的服务器是合法的?


http和https的区别:https做了很多安全的考量,但与http相比,一定会不可避免的慢一些。

长连接与短连接

连接的打开和关闭是应用层控制的,TCP本身提供的是建立连接和断开连接的功能,至于要不要建立以及断开,由应用层决定。
http本身是有能力控制连接的打开和关闭的。

长连接:在一条网络信道中,建立一次,释放一次,传送多种网络资源。可以明显减少建立和释放连接的成本,提高效率。

即便是这样,资源在这条信道上也是串行的。但理论上,服务器拥有同时处理多个请求的能力。
TCP会保证request数据按序到达,所以http不担心传送数据时会发生数据变乱的问题。

http1.0 用的是短连接,因为早期的时候网页比较简单,
http1.1 用的是长连接,因为如今的网页资源变得复杂了许多。

二、运输层

UDP

UDP协议端格式

TCP

  • 为什么会有可靠性这一概念?

因为网络传输,线路更长,会出现很多问题。

  • 不可靠都有哪些情况?

丢包乱序;数据出错;接收缓冲区满等。

TCP协议会保证可靠性,解决一些问题,因此它的格式会更复杂一些。

TCP协议端格式


TCP报头长度浮动,在20~60字节之间。

[选项] 部分带与不带,以及带多少的问题取决于[4位首部长度]。
4位首部长度:表示该TCP首部有多少个32位bit(也就是有多少个4字节)。 所以TCP头部最大长度是15 * 4 = 60,因为4位首部长度的范围在0000 ~ 1111之间,一般默认填0101(5),也就是20个字节。

因此[选项]部分最多是40个字节。

  • TCP协议是怎么做到将报头和有效载荷分离的?

首先拿到报文,先读取20个字节,将[4位首部长度]拿出来分析,如果它是20,剩下的再继续读就是数据了;如果它大于20,说明还有x-20个字节(选项部分)要读。

与UDP相比,TCP段格式中没有数据总长度,这是因为TCP不需要按数据块交付。当它收到数据时,只需要把所有的数据按照顺序放到缓冲区里。因为它是面向字节流的,上层怎么读由上层决定,所以它也没有所谓的“结束”概念。

  • 当报头和有效载荷分离之后,TCP怎么做到向上交付?

首先,由目的端口号决定交付给上层的哪个进程(在内核层面利用哈希算法,找到对应进程)。

  • 如何证明报文的完整性呢?

由[校验和]这个部分来验证完整性。

可靠性的理解
要保证可靠性的前提条件是,先保证对方把数据收到了。
在互联网通信时,没有所谓的绝对可靠性,因为永远有一条最新的消息是没有确认的,因此就无法保证对方是否收到。
保证可靠性最核心的思想:我们只能对收到确认的数据负责。只要收到了对应的应答,我们认为,之前的数据对方已经收到。

TCP叫做基于确认应答机制。保证对方收到。
并不是对ACK保证可靠性,而是通过ACK保证上次发的消息是可靠的。

32位序号:发送数据的序号,为保证接收方收到数据按序到达。
32位确认序号:是为了区分谁应答的谁这个问题,是ACK的序号。规定对它原始报文的序号加1进行ACK。

  • 举例
    发送方收到接收方的ACK7:发送方认为6号之前的所有内容已经收到,我应该从7开始发。
    如果发送方发送678号数据,此时接收方给发送方的确认序号ACK应分别填入7, 8, 9。
    如果给发送方的确认ACK 7, 8号丢了,只收到了9,那么发送方会认为9之前的所有数据接收方已经全部收到了,接收方发的ACK填的是9,所以下次发数据应从9号开始发。

因为序号与确认序号的存在,就允许TCP出现少量的丢包问题。

  • 为什么要有序号与确认序号?

序号是为了解决接收方接收数据按序到达,确认序号解决的是确认应答的问题。

  • 为什么序号有两套,只设计一套行不行?

A给B发消息时,B最关心A的序号;而当A收到B的应答时,A最关心B的确认序号
因为TCP是全双工,A / B可以同时做接收方和发送方,可能存在双方同时在通信的情况。因此在不同的角色中双方关心的序号是不一样的,所以存在序号和确认序号。

总结
1、通过ACK和确认序号,解决了丢包问题。
ACK:证明是否丢包;确认序号:丢了哪个包。
2、乱序问题通过序号解决。

TCP解决了不可靠的情况,因此它是可靠的。

之前我们基于应用层写程序时,并不关心上述所说的这些通信细节。这些都是TCP在帮我们做,基于它所提供的send等重要接口。

窗口大小
TCP具有接收缓冲区和发送缓冲区,且有大小。
接收方接收数据的本质是要把这个数据read/recv上去,之后应用层要对数据做加工处理,这个过程可能会比较复杂,时间也就会较长。如果发送方发的太快,接收方来不及接收,此时上层来不及把数据从内核读取到应用层,有可能导致内核中出现数据的积压,引发缓冲区满了的问题,再发送过来的报文收不到就会丢失。但TCP本身并不怕报文丢失,可是重传会浪费网络资源。

因此,引入窗口大小:指的是发送方的接收缓冲区当中剩余空间的大小。

根据接收端的接收能力,来决定发送端的发送速度,这个机制就叫做流量控制。
作为发送方,要给接收方发数据,就要把发送方的窗口大小填上,这样接收方就知道了发送方的接收窗口大小,发多少数据,它就会很清楚了。

六个标志位
当服务器收到了大量的报文,如何区分这个报文的意向?是发送给服务器的数据呢,还是想要跟服务器建立连接呢?因此,对于形形色色的TCP报文,我们必须得对它们进行分类。

URG:紧急指针是否有效。它表面,此报文段中有紧急数据,需要优先被处理,尽快传输。
紧急指针:指出了紧急数据的末尾在报文中的位置。
ACK:确认。除了第一次发送数据不需要设置之外,基本上每一次都会需要设置。因为每一个报文都承担者两种作用:对对方的数据进行ACK;给对方发数据。
PSH:尽快交付给上层,不再等到整个缓存满了再向上交付。
RST:TCP建立连接需要三次握手,但三次握手不一定会建立成功。

SYN:建立连接。
FIN:释放连接。

之前我们调用的应用层接口send和recv,并不是把数据发到网络里,再从网络里把数据读上来。
send本质是在做:把用户层的数据拷到缓冲区里。
recv本质是在做:从缓冲区里读数据,拷贝到用户层。
在这其中,就会涉及发送缓冲区满(发送条件不满足)和接收缓冲区空(接收条件不满足)的问题。所以才会出现send和recv阻塞的情况。

超时重传

如果主机A在一个特定时间间隔内没有收到B发来的确认应答,就会进行重发。

超时的时间随着网络环境的不同,TCP保证高效通信,会动态计算。

连接(三次握手,四次挥手)

  • 1、如何理解连接?

连接本身是有成本的:空间和时间。

  • 2、TCP是面向连接的,双方三次握手成功之后,意味着客户端和服务器都要维护连接。

  • 3、为什么是三次握手?

一次握手和两次握手,极容易收到一种攻击方式:SYN洪水攻击。意味着,只要客户端无条件的发送SYN,服务器就立马建立连接,此时就占用了服务器的一点点资源。如果大量的客户端发送大量的SYN,那么服务器很快就挂掉了。但三次握手也没有完全避免洪水攻击。

TCP是全双工的,对于双方来讲,都承担着既能发送又能接收的角色。因此在通信之前,要把双方的通信信道先验证一下。
三次握手就把客户端和服务器这两个角色分别进行了发送和接收的通信信道的验证!在这个过程中,客户端和服务器都至少有一次收和发,验证了自己的全双工通信。
反观两次握手,服务器没有办法验证它发送的最新的那条消息,客户端是否收到。

三次握手对应三个报文,三个报文中的任何一个都有可能丢失。第一个报文的丢失我们并不担心,对服务器无影响;第二个报文的丢失我们也不担心,它的丢失只是意味着双方三次握手没有完成,即双方就不会为了通信把连接建立好,也就没有为了该连接投入成本。
但第三个丢失会产生影响:客户端会认为连接建立好了,但此时服务器认为还没有完成三次握手。
总的来说,在n次握手时,前n-1次的丢失,我们是不担心的,我们担心的是第n次的丢失
但最后一个报文丢了,一定要有“背锅”的角色,因为一定要有一个角色去发最后一个报文,这个角色永远认为连接是建立成功的。
这个“背锅”的角色一定是要客户端。因为服务器是一对多的,意味着有可能有大量的请求向它发送,一旦因为网络不好,会造成丢失最后一个报文成了普遍现象。对服务器来讲,丢失最后一个报文的概率大大增加。因为它面对的是多个客户,最终会导致服务器上挂接了大量的废弃连接。极大的浪费了服务器的资源,我们应该保护的是服务器。
倘若让客户端来承担这个责任,这个报文的丢失,对它的影响并不大,因为客户端所承载的连接最多就是使用这个电脑的用户所发起的网络请求。

所以重要原因有两点:

用最小成本验证全双工
② 让服务器不要出现连接建立的误判情况,减少服务器的资源浪费。

  • 4、为什么是四次挥手?

因为断开连接是双方的事情,且TCP是全双工的,所以客户端向服务器发送数据的信道和服务器向客户端发送的那个信道都要断开。


CLOSE_WAIT的意义
如果查看到服务器挂满了大量的CLOSE_WAIT,说明服务器本身有bug,上层没有关闭文件描述符,进而导致服务器一直处于CLOSE_WAIT状态。

TIME_WAIT的意义

假如没有这个TIME_WAIT状态,服务器发送FIN,客户端直接进入CLOSED状态,客户端会认为连接断开完成,释放连接资源。但如果最后一个ACK丢了,客户端并不会在意,导致服务器没有收到ACK,进而认为客户端没有收到FIN,就会重传。但此时连接已经断开了,服务器的资源就会被浪费。

所以要加一个TIME_WAIT状态。客户端发送完最后一个ACK之后,不急着断开连接,而是等一等,这个状态要求主动断开连接的一方要进行等待。如果客户端再次收到FIN,就证明服务器没收到ACK。
“没有消息便是好消息”:如果在等的这个周期内,没有收到FIN,即认为对方已经收到了ACK。
但如果服务器因网络问题多次重传也没有把FIN发过去,此时客户端等待结束,关闭,服务器也会强制关闭。

意义:
1、尽量保证最后一个ACK被对方收到,进而尽快释放服务器的资源,保证服务器的利益。
2、等待历史数据在网络上进行消散。

TIME_WAIT一般设置为2*MSL(MSL:最大传输数据时间)

滑动窗口

每一个发送的数据段,都要给一个ACK确认应答,收到ACK后再发送下一个数据段,这样做效率很低。如果我们一次发送多条数据,就可以大大的提高效率。

如何理解滑动窗口?
认为是发送缓冲区的一部分。
滑动窗口就是一段范围,想象成相当于数组的下标left,right
滑动窗口右移,left++,right++;
当对方接收能力为0,此时left==right。

出现了丢包,分两种情况:
(1)数据包已经抵达,对应ACK丢失。
这种情况下,部分ACK丢了并不要紧,因为可以通过后续的ACK进行确认
(2)数据包直接丢失。
当某一段报文段丢失之后,发送端会一直收到对应序号的ACK。如果发送端主机连续三次收到了同样一个序号的ACK,就会将对应的数据重新发送。这种机制被称为快重传。

快重传适用于解决同时传送大量数据出现丢包的问题,而超时重传弥补了快重传不适用的场景,也就是三个及以下报文的发送时。二者互补。

拥塞控制

为什么要进行拥塞控制?判定网络出问题了。
怎么判定?大量数据丢包了。


窗口大小:TCP报文段的首部格式中带有。
滑动窗口:不用收到ACK,直接可以发的数据大小。
拥塞窗口:取决于当前网络的拥塞程度,并动态地变化着。发送端利用拥塞窗口根据网络的拥塞情况调整发送的数据量。

延迟应答

A给B发消息,B没有直接ACK,而是先等一等,等上层(应用层)把B的数据取走,接收缓冲区空出来,B再进行ACK,这样填的那个wnd窗口值就更大了。
主要解决的是效率的问题。

listen的第二个参数

排队的意义:保证在大部分时间段服务器的资源是被百分之百使用的,但队列不能太长。

Linux内核协议栈为一个TCP连接管理构建两个队列:

  1. 半连接队列(用来保存处于SYN_SENT和SYN_RECV状态的请求)
  2. 全连接队列(accpetd队列)(用来保存处于established状态,但是应用层没有调用accept取走的请求)

listen的第二个参数,叫做连接队列(全连接)的长度。

  • 为什么listen的第二个参数要+1才是全连接队列的长度

因为内核代码在比较连接数是否已经达到上限时,用的是>,并非>=

TCP的复杂体现在:
可靠性:校验和;序列号(按序到达);确认应答;超时重发;连接管理;流量控制;拥塞控制;
提高效率:滑动窗口;快速重传;延迟应答;捎带应答


网络基础Ⅱ(应用层 | 运输层)相关推荐

  1. 网络基础应用层--HTTP协议

    网络基础应用层--HTTP协议 一.应用层协议 (一)应用层协议概念 (二)自定义协议概念 (三)数据格式如何定义最优 (四)结构体的二进制序列化 二.HTTP协议 (一)HTTP协议 1.请求-响应 ...

  2. 【Linux】网络基础--应用层详解

    网络基础--应用层 ⏰应用层

  3. HTTP协议【网络基础/应用层】

    文章目录 1. 网络基础 TCP/IP 2. 与HTTP密切相关的协议 2.1 负责传输的 IP 协议 路由选择 2.2 确保可靠性的 TCP 协议 三次握手 2.3 负责域名解析的 DNS 服务 2 ...

  4. 前端网络基础-应用层DNS协议

    目录 初识域名 正向解析和反向解析 DNS解析 主机本地hosts文件实现DNS解析 浏览器缓存实现DNS解析 本地DNS服务器实现DNS解析 域名的组成 DNS迭代解析 DNS递归解析 DNS协议 ...

  5. 网络基础 -- 应用层HTTP协议

    目录 应用层(TCP/IP协议中的应用层/HTTP协议) HTTP协议 URL -- 统一资源定位符 UrlEncode / UrlDecode HTTP协议格式 概述 HTTP 请求消息Reques ...

  6. 前端网络基础-应用层HTTP协议

    目录 什么是HTTP协议 URL与URI HTTP协议的报文结构 HTTP请求方法 GET请求方法 POST请求方法 HTTP响应状态码 HTTP报文头 HTTP无状态性 什么是HTTP协议 HTTP ...

  7. 最常问的网络基础面试问题整理

    其他专题也也还在整理中,包括Redis,数据库,操作系统,Spring等 OSI七层模型 物理层 首先解决两台物理机之间的通信需求,具体就是机器A往机器B发送比特流,机器B能收到比特流. 物理层主要定 ...

  8. 做接口测试前必备的网络基础知识,你get了吗?

    在面试时,不管是面试功能测试.自动化测试.测试开发乃至性能测试,都会问到计算机网络基础相关知识.今天主要介绍一些高频的网络基础面试题目,网络情缘一线牵,珍惜这段缘,如果觉得有帮助,欢迎留言.点赞.转发 ...

  9. 网络基础之信息的生成与传递

    今天介绍网络基础中的信息的生成与传递 首先我们的数据在传递过程中会经过这四个层:应用层.运输层.网络层.链路层 我们的数据在应用层序中产生,加上Appl首部传输到运输层的TCP段,形成了TCP段的应用 ...

  10. 计算机---网络基础小知识点11.17

    计算机---网络基础小知识点 彩虹色------------ 彩虹色------------ 1.网络的拓扑结构可反映出网中各实体间的结构关系,是建设计算机网络的第一步,是实现各种网络协议的基础,它对 ...

最新文章

  1. 基于OpenCV的数字识别系统
  2. 如何破除“唯论文”?详解伯克利“科研重工业模式”的成功经验
  3. redhat及deban系列linux软件管理的一些问题
  4. linux服务器不能访问,无法在远程Linux服务器上访问tomcat
  5. 第二章 OpenResty(Nginx+Lua)开发入门
  6. 手写自定义注解实现思路
  7. dt程序网站服务器配置,ZKWeb 官网与演示站点的部署步骤 (Linux + Nginx + Certbot)
  8. 关于Javascript, php的web公开课笔记
  9. C语言常用开发环境IDE
  10. KMeans聚类分析实战——如何把城市划分成不同的种类
  11. 用手机打开word图表位置很乱_干货 | 论文格式调半天?Word攻略帮你统统都搞定...
  12. 一文掌握 Java8 Stream 中 Collectors 的 24 个操作
  13. hive sql中常用技巧
  14. Android系统体系结构
  15. Java实现局域网聊天软件分享
  16. 斐迅路由器刷华硕固件
  17. 横版过关2d游戏c语言代码,如何制作一个横版格斗过关游戏(2) Cocos2d-x 2.0.4
  18. 基于Python(Django)+MongoDB实现的(Web)新闻采集和订阅系统【100010319】
  19. linux下autocad完美替代品ARES Commander的安装运行
  20. PostgreSQL 中的单引号与双引号

热门文章

  1. 公众号关键词文章排名,公众号文章排名靠什么决定
  2. 第1周 - 课程材料
  3. python 中文字符串分割与拼接
  4. 性能测试--RoadRunner 2 Controller
  5. 【JS】Function 函数简解
  6. 2021-06-19复习java Collection集合 Iterator接口_迭代器 增强for循环 泛型
  7. oracleclient和plsql安装注意事项
  8. 高德地图广告开户找哪里?高德地图推广广告多少钱?
  9. oracle 笔记4(Fundamentals II)
  10. 私有云 openstack部署