http,tcp,udp协议深度分析(硬核推荐)

文章目录

  • 前言
  • 一、网络分层原理
    • 1.现实世界中的复杂网络环境
    • 2.OSI七层协议和TCP/IP协议
      • 第一层:物理层
      • 第二层:数据链路层
      • 第三层:网络层
      • 第四层:传输层
      • 第五层:会话层
      • 第六层:表示层
      • 第七层:应用层
    • 3. 一个HTTP请求的分层解析流程
  • 二、HTTP协议
    • 1.基本概念
      • 超文本传输协议(HyperText Transfer Protocol,HTTP) :
      • 什么是无状态协议?
      • 什么是有状态协议?
    • 2.HTTP报文布局
      • 请求报文格式:
      • 请求行报文格式:
      • 15种HTTP请求方法:
      • HTTP请求头信息对照表:
      • 响应报文格式:
      • 响应行报文格式:
      • HTTP状态码对照表:
      • HTTP响应头信息对照表:
    • 3.一个http请求的完整过程
    • 4.通过火狐浏览器分析请求与响应报文
      • 请求报文分析:
      • 响应报文分析:
  • 三、TCP协议和UDP协议
    • 1.UDP报文
      • UDP报文整体布局:
      • UDP的首部格式(UDP头):
      • UDP协议特点:
    • 2.TCP报文
      • TCP报文整体布局:
      • TCP协议特点:
    • 3.TCP三次握手
      • 三次握手过程分析
      • 三次握手实践
      • SYN攻击
    • 4.TCP四次挥手
      • 四次挥手过程分析
      • 为什么“握手”是三次,“挥手”却要四次?(京东面试题)
      • 为什么客户端在TIME-WAIT阶段要等2MSL?(携程面试题)
    • 5.面向字节流
    • 6.TCP拆包和粘包问题
      • 图解什么是拆包和粘包?
      • 为什么会发生TCP粘包、拆包呢?(知乎二面)
      • 如何处理粘包、拆包问题?(知乎二面)
    • 7.TCP异常情况
    • 总结


前言

平时上网冲浪逛淘宝,或者给微信好友发送一条消息时,这条消息(或者叫数据更为准确)会在网络上进行传输,但在实际网络这条数据是怎么安全被接收者接收的,今天我们就来聊一聊。


一、网络分层原理

1.现实世界中的复杂网络环境

在纽约的我想给一位成都的小姐姐发送一条消息(后面都叫数据),那么这条消息由数字信号转换成模拟信号在网络上进行传输(通过网线或者光纤),但这条数据将会面临许多复杂的传输环境,比如模拟信号受到磁场影响或极端天气影响出现衰减,传输过程中丢包等,如下图:
http,tcp,udp协议深度分析(硬核推荐)_第1张图片
数据在上面的网络中传输显得极为复杂,为了简化网络的复杂度,网络通信的不同方面被分解为多层次结构,使得每个层次分工明确,并且每一层只与紧挨着的上一层或者下一层进行交互,.各层之间相互独立,即不需要知道低层的结构,只要知道是通过层间接口所提供的服务,这样大大提高了灵活性,只要接口不变就不会因层的变化(甚至是取消该层)而变化,各层采用最合适的技术实现而不影响其他层。这也有利于促进标准化。

2.OSI七层协议和TCP/IP协议

OSI七层协议: Open System Interconnect的缩写,意为开放式系统互联。开放式系统互联模型是一个参考标准,解释协议相互之间应该如何相互作用,OSI是制定的适用于全世界计算机网络的统一标准,是一种理想状态。
TCP/IP协议: 是美国国防部发明的,是让互联网成为了目前这个样子的标准之一。
http,tcp,udp协议深度分析(硬核推荐)_第2张图片

IOS七层参考模型 TCP/IP协议 对应的网络协议 对应的网络设备
应用层 应用层 DNS,HTTP,FTP,TFTP,SSH,SMTP,SNMP,Telnet /
表示层 / /
会话层 / /
传输层 传输层 TCP,UDP 四层交换机、四层路由器
网络层 网际层 IP,ICMP,ARP,RARP,AKP,UUCP 路由器、三层交换机
数据链路层 网络接口层 FDDI,Ethernet,Arpanet,PPP,SLIP,PDN 网桥、以太网交换机、网卡
物理层 IEEE802.1A,IEEE802.2 ~ IEEE802.11 中继器、集线器、双绞线

第一层:物理层

物理层是参考模型中的最底层,主要定义了系统的电气、机械、过程和功能标准。 如:电压、物理数据速率、最大传输距离、物理联接器和其他的类似特性。物理层的主要功能是利用传输介质为数据链路层提供物理联接,负责数据流的物理传输工作。物理层传输的基本单位是比特流(bit),即0和1,也就是最基本的电信号或光信号,是最基本的物理传输特征。

第二层:数据链路层

在物理层提供比特流服务的基础上,建立相邻结点之间的数据链路,通过差错控制提供数据帧(Frame)在信道上无差错的传输,并进行各电路上的动作系列。数据链路层在不可靠的物理介质上提供可靠的传输。该层的作用包括:物理地址寻址、数据的成帧、流量控制、数据的检错、重发等。 在这一层,数据的单位称为帧(frame)。数据链路层协议的代表包括:SDLC、HDLC、PPP、STP、帧中继等。

第三层:网络层

在 计算机网络中进行通信的两个计算机之间可能会经过很多个数据链路,也可能还要经过很多通信子网。网络层的任务就是选择合适的网间路由和交换结点, 确保数据及时传送。网络层将数据链路层提供的帧组成数据包,包中封装有网络层包头,其中含有逻辑地址信息——源站点和目的站点地址的网络地址。如果你在谈论一个IP地址,那么你是在处理第3层的问题,这是“数据包”问题,而不是第2层的“帧”。IP是第3层问题的一部分,此外还有一些路由协议和地 址解析协议(ARP)。有关路由的一切事情都在这第3层处理。地址解析和路由是3层的重要目的。网络层还可以实现拥塞控制、网际互连等功能。在这一层,数据的单位称为数据包(packet)。网络层协议的代表包括:IP、IPX、RIP、OSPF等。

第四层:传输层

第4层的数据单元也称作数据包(packets)。但是,当你谈论TCP等具体的协议时又有特殊的叫法,TCP的数据单元称为数据段 (segments)而UDP协议的数据单元称为“数据报(datagrams)”。这个层负责获取全部信息,因此,它必须跟踪数据单元碎片、乱序到达的 数据包和其它在传输过程中可能发生的危险。第4层为上层提供端到端(最终用户到最终用户)的透明的、可靠的数据传输服务。所为透明的传输是指在通信过程中 传输层对上层屏蔽了通信传输系统的具体细节。 传输层协议的代表包括:TCP、UDP、SPX等。

第五层:会话层

在会话层及以上的高层次中,数据传送的单位不再另外命名,而是统称为报文。会话层不参与具体的传输,主要功能是负责维护两个节点之间的传输联接,确保点到点传输不中断,以及管理数据交换等功能。会话层在应用进程中建立、管理和终止会话。会话层还可以通过对话控制来决定使用何种通信方式,全双工通信或半双工通信。会话层通过自身协议对请求与应答进行协调。

第六层:表示层

表示层为在应用过程之间传送的信息提供表示方法的服务。表示层以下各层主要完成的是从源端到目的端可靠地的数据传送,而表示层更关心的是所传送数据的语法和语义。 表示层的主要功能是处理在两个通信系统中交换信息的表示方式,主要包括数据格式变化、数据加密与解密、数据压缩与解压等。在网络带宽一定的前提下数据压缩的越小其传输速率就越快,所以表示层的数据压缩与解压被视为掌握网络传输速率的关键因素。表示层提供的数据加密服务是重要的网络安全要素,其确保了数据的安全传输,也是各种安全服务最为重视的关键。表示层为应用层所提供的服务包括:语法转换、语法选择和联接管理。

第七层:应用层

应用层为操作系统或网络应用程序提供访问网络服务的接口。应用层中包含了若干独立的用户通用服务协议模块,为网络用户之间的通信提供专用的程序服务。需要注意的是应用层并不是应用程序,而是为应用程序提供服务。应用层协议的代表包括:Telnet、FTP、HTTP、SNMP等。

相同点:
OSI和TCP/IP的相同点是二者均采用层次结构,而且都是按功能分层。都是负责为用户提供真正的端对端的通信服务,也对高层屏蔽了底层网络的实现细节。
不同点:

  • OSI分七层,自下而上分为物理层、数据链路层、网络层、传输层、会话层、表示层和应用层,而TCP/IP分四层:网络接口层、网际层、传输层和应用层。

  • OSI层次间存在严格的调用关系,两个(N)层实体的通信必须通过下一层(N-1)层实体,不能越级,而TCP/IP可以越过紧邻的下一层直接使用更低层次所提供的服务,因而减少了一些不必要的开销,提高了协议的效率。

  • OSI先有模型,再有协议,比较适合理论上探讨。TCP/IP先有协议,再有模型,已得到广泛的实际应用。

3. 一个HTTP请求的分层解析流程

http,tcp,udp协议深度分析(硬核推荐)_第3张图片

二、HTTP协议

1.基本概念

超文本传输协议(HyperText Transfer Protocol,HTTP) :

http是一个简单的请求-响应协议,一种无状态的,以请求/应答方式运行的协议,请求和响应消息的头以ASCII码形式给出;而消息内容则具有一个类似MIME的格式,它使用可扩展的语义和自描述消息格式。

什么是无状态协议?

无状态是指Web浏览器与Web服务器之间不需要建立持久的连接,这意味着当一个客户端向服务器端发出请求,然后Web服务器返回响应,连接就被关闭了,在服务器端不保留连接的有关信息。也就是说,HTTP请求只能由客户端发起,而服务器不能主动向客户端发送数据。HTTP协议是一种典型的无状态协议。

什么是有状态协议?

有状态指的是,客户端或者服务端需要维护一个状态。TCP协议实际上是双方都维护了一个状态,双方都变成已连接的状态,才可以开始传输数据,任何一个人掉线都不能发送消息;双方都变成连接关闭状态时,这时候双方都释放需要维护这个状态的资源。

2.HTTP报文布局

请求报文格式:

http,tcp,udp协议深度分析(硬核推荐)_第4张图片

HTTP协议的请求报文由三大部分组成:

请求行:描述请求的基本信息,包含了请求方法(METHOD),请求资源的URI,HTTP版本号。
头部字段集合: 使用 key-value 形式更详细地说明报文,包含了请求头,通用信息头,实体头

  • 请求头:允许客户端传递关于自身的信息和希望的响应形式。
  • 通用信息头:即可用于请求,也可用于响应,是作为一个整体而不是特定资源与事务相关联。
  • 实体头:定义被传送资源的信息。即可用于请求,也可用于响应。

报文主体:实际传输的数据,它不一定是纯文本,可以是图片、视频 等二进制数据。

请求行报文格式:

http,tcp,udp协议深度分析(硬核推荐)_第5张图片

  • 请求方法:如 GET/HEAD/PUT/POST,表示对资源的操作;
  • 请求目标:通常是一个 URI,标记了请求方法要操作的资源;
  • 版本号:表示报文使用的 HTTP 协议版本。

15种HTTP请求方法:

序号 方法 描述
1 GET 请求指定的页面信息,并返回实体主体。
2 HEAD 类似于get请求,只不过返回的响应中没有具体的内容,用于获取报头。
3 POST 向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。POST请求可能会导致新的资源的建立和/或已有资源的修改。
4 PUT 从客户端向服务器传送的数据取代指定的文档的内容。
5 DELETE 请求服务器删除指定的页面。
6 CONNECT HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器。
7 OPTIONS 允许客户端查看服务器的性能。
8 TRACE 回显服务器收到的请求,主要用于测试或诊断。
9 PATCH 实体中包含一个表,表中说明与该URI所表示的原内容的区别。
10 MOVE 请求服务器将指定的页面移至另一个网络地址。
11 COPY 请求服务器将指定的页面拷贝至另一个网络地址。
12 LINK 请求服务器建立链接关系。
13 UNLINK 断开链接关系。
14 WRAPPED 允许客户端发送经过封装的请求。
15 Extension-mothed 在不改动协议的前提下,可增加另外的方法。

HTTP请求头信息对照表:

Header 解释 示例
Accept 指定客户端能够接收的内容类型 Accept: text/plain, text/html
Accept-Charset 浏览器可以接受的字符编码集。 Accept-Charset: iso-8859-5
Accept-Encoding 指定浏览器可以支持的web服务器返回内容压缩编码类型。 Accept-Encoding: compress, gzip
Accept-Language 浏览器可接受的语言 Accept-Language: en,zh
Accept-Ranges 可以请求网页实体的一个或者多个子范围字段 Accept-Ranges: bytes
Authorization HTTP授权的授权证书 Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
Cache-Control 指定请求和响应遵循的缓存机制 Cache-Control: no-cache
Connection 表示是否需要持久连接。(HTTP 1.1默认进行持久连接) Connection: close
Cookie HTTP请求发送时,会把保存在该请求域名下的所有cookie值一起发送给web服务器。 Cookie: $Version=1; Skin=new;
Content-Length 请求的内容长度 Content-Length: 348
Content-Type 请求的与实体对应的MIME信息 Content-Type: application/x-www-form-urlencoded
Date 请求发送的日期和时间 Date: Tue, 15 Nov 2010 08:12:31 GMT
Expect 请求的特定的服务器行为 Expect: 100-continue
From 发出请求的用户的Email From: [email protected]
Host 指定请求的服务器的域名和端口号 Host: www.zcmhi.com
If-Match 只有请求内容与实体相匹配才有效 If-Match: “737060cd8c284d8af7ad3082f209582d”
If-Modified-Since 如果请求的部分在指定时间之后被修改则请求成功,未被修改则返回304代码 If-Modified-Since: Sat, 29 Oct 2010 19:43:31 GMT
If-None-Match 如果内容未改变返回304代码,参数为服务器先前发送的Etag,与服务器回应的Etag比较判断是否改变 If-None-Match: “737060cd8c284d8af7ad3082f209582d”
If-Range 如果实体未改变,服务器发送客户端丢失的部分,否则发送整个实体。参数也为Etag If-Range: “737060cd8c284d8af7ad3082f209582d”
If-Unmodified-Since 只在实体在指定时间之后未被修改才请求成功 If-Unmodified-Since: Sat, 29 Oct 2010 19:43:31 GMT
Max-Forwards 限制信息通过代理和网关传送的时间 Max-Forwards: 10
Pragma 用来包含实现特定的指令 Pragma: no-cache
Proxy-Authorization 连接到代理的授权证书 Proxy-Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
Range 只请求实体的一部分,指定范围 Range: bytes=500-999
Referer 先前网页的地址,当前请求网页紧随其后,即来路 Referer: http://www.zcmhi.com/archives/71.html
TE 客户端愿意接受的传输编码,并通知服务器接受接受尾加头信息 TE: trailers,deflate;q=0.5
Upgrade 向服务器指定某种传输协议以便服务器进行转换(如果支持) Upgrade: HTTP/2.0, SHTTP/1.3, IRC/6.9, RTA/x11
User-Agent User-Agent的内容包含发出请求的用户信息 User-Agent: Mozilla/5.0 (Linux; X11)
Via 通知中间网关或代理服务器地址,通信协议 Via: 1.0 fred, 1.1 nowhere.com (Apache/1.1)
Warning 关于消息实体的警告信息 Warn: 199 Miscellaneous warning

响应报文格式:

http,tcp,udp协议深度分析(硬核推荐)_第6张图片
HTTP协议的响应报文由三大部分组成:

响应行:描述响应的基本信息包含HTTP版本号,状态码(STATUS CODE),原因(REASON)。
头部字段集合: 使用 key-value 形式更详细地说明报文,包含了响应头,通用信息头,实体头

  • 响应头:服务器用于传递自身信息的响应。
  • 通用信息头:即可用于请求,也可用于响应,是作为一个整体而不是特定资源与事务相关联。
  • 实体头:定义被传送资源的信息。即可用于请求,也可用于响应。

报文主体:实际传输的数据,它不一定是纯文本,可以是图片、视频 等二进制数据。

响应行报文格式:

http,tcp,udp协议深度分析(硬核推荐)_第7张图片

  • 版本号:表示报文使用的 HTTP 协议版本;
  • 状态码:一个三位数,用代码的形式表示处理的结果,比如 200 是成功,500 是服务器错误;
  • 原因:作为数字状态码补充,是更详细的解释文字,帮助人理解原因。

HTTP状态码对照表:

HTTP状态码由三个十进制数字组成,第一个十进制数字定义了状态码的类型,后两个数字没有分类的作用。HTTP状态码共分为5种类型

  • 1xx:信息,服务器收到请求,需要请求者继续执行操作
  • 2xx:成功,操作被成功接收并处理
  • 3xx:重定向,需要进一步的操作以完成请求
  • 4xx:客户端错误,请求包含语法错误或无法完成请求
  • 5xx:服务器错误,服务器在处理请求的过程中发生了错误
状态码 状态码英文名称 描述
1开头的状态码
100 Continue 继续。客户端应继续其请求
101 Switching Protocols 切换协议。服务器根据客户端的请求切换协议。只能切换到更高级的协议,例如,切换到HTTP的新版本协议
2开头的状态码
200 OK 请求成功。一般用于GET与POST请求
201 Created 已创建。成功请求并创建了新的资源
202 Accepted 已接受。已经接受请求,但未处理完成
203 Non-Authoritative Information 非授权信息。请求成功。但返回的meta信息不在原始的服务器,而是一个副本
204 No Content 无内容。服务器成功处理,但未返回内容。在未更新网页的情况下,可确保浏览器继续显示当前文档
205 Reset Content 重置内容。服务器处理成功,用户终端(例如:浏览器)应重置文档视图。可通过此返回码清除浏览器的表单域
206 Partial Content 部分内容。服务器成功处理了部分GET请求
3开头的状态码
300 Multiple Choices 多种选择。请求的资源可包括多个位置,相应可返回一个资源特征与地址的列表用于用户终端(例如:浏览器)选择
301 Moved Permanently 永久移动。请求的资源已被永久的移动到新URI,返回信息会包括新的URI,浏览器会自动定向到新URI。今后任何新的请求都应使用新的URI代替
302 Found 临时移动。与301类似。但资源只是临时被移动。客户端应继续使用原有URI
303 See Other 查看其它地址。与301类似。使用GET和POST请求查看
304 Not Modified 未修改。所请求的资源未修改,服务器返回此状态码时,不会返回任何资源。客户端通常会缓存访问过的资源,通过提供一个头信息指出客户端希望只返回在指定日期之后修改的资源
305 Use Proxy 使用代理。所请求的资源必须通过代理访问
306 Unused 已经被废弃的HTTP状态码
307 Temporary Redirect 临时重定向。与302类似。使用GET请求重定向
4开头的状态码
400 Bad Request 客户端请求的语法错误,服务器无法理解
401 Unauthorized 请求要求用户的身份认证
402 Payment Required 保留,将来使用
403 Forbidden 服务器理解请求客户端的请求,但是拒绝执行此请求
404 Not Found 服务器无法根据客户端的请求找到资源(网页)。通过此代码,网站设计人员可设置"您所请求的资源无法找到"的个性页面
405 Method Not Allowed 客户端请求中的方法被禁止
406 Not Acceptable 服务器无法根据客户端请求的内容特性完成请求
407 Proxy Authentication Required 请求要求代理的身份认证,与401类似,但请求者应当使用代理进行授权
408 Request Time-out 服务器等待客户端发送的请求时间过长,超时
409 Conflict 服务器完成客户端的PUT请求是可能返回此代码,服务器处理请求时发生了冲突
410 Gone 客户端请求的资源已经不存在。410不同于404,如果资源以前有现在被永久删除了可使用410代码,网站设计人员可通过301代码指定资源的新位置
411 Length Required 服务器无法处理客户端发送的不带Content-Length的请求信息
412 Precondition Failed 客户端请求信息的先决条件错误
413 Request Entity Too Large 由于请求的实体过大,服务器无法处理,因此拒绝请求。为防止客户端的连续请求,服务器可能会关闭连接。如果只是服务器暂时无法处理,则会包含一个Retry-After的响应信息
414 Request-URI Too Large 请求的URI过长(URI通常为网址),服务器无法处理
415 Unsupported Media Type 服务器无法处理请求附带的媒体格式
416 Requested range not satisfiable 客户端请求的范围无效
417 Expectation Failed 服务器无法满足Expect的请求头信息
5开头的状态码
500 Internal Server Error 服务器内部错误,无法完成请求
501 Not Implemented 服务器不支持请求的功能,无法完成请求
502 Bad Gateway 充当网关或代理的服务器,从远端服务器接收到了一个无效的请求
503 Service Unavailable 由于超载或系统维护,服务器暂时的无法处理客户端的请求。延时的长度可包含在服务器的Retry-After头信息中
504 Gateway Time-out 充当网关或代理的服务器,未及时从远端服务器获取请求
505 HTTP Version not supported 服务器不支持请求的HTTP协议的版本,无法完成处理

HTTP响应头信息对照表:

Header 解释 示例
Accept-Ranges 表明服务器是否支持指定范围请求及哪种类型的分段请求 Accept-Ranges: bytes
Age 从原始服务器到代理缓存形成的估算时间(以秒计,非负) Age: 12
Allow 对某网络资源的有效的请求行为,不允许则返回405 Allow: GET, HEAD
Cache-Control 告诉所有的缓存机制是否可以缓存及哪种类型 Cache-Control: no-cache
Content-Encoding web服务器支持的返回内容压缩编码类型。 Content-Encoding: gzip
Content-Language 响应体的语言 Content-Language: en,zh
Content-Length 响应体的长度 Content-Length: 348
Content-Location 请求资源可替代的备用的另一地址 Content-Location: /index.html
Content-MD5 返回资源的MD5校验值 Content-MD5: Q2hlY2sgSW50ZWdyaXR5IQ==
Content-Range 在整个返回体中本部分的字节位置 Content-Range: bytes 21010-47021/47022
Content-Type 返回内容的MIME类型 Content-Type: text/html; charset=utf-8
Date 原始服务器消息发出的时间 Date: Tue, 15 Nov 2010 08:12:31 GMT
ETag 请求变量的实体标签的当前值 ETag: “737060cd8c284d8af7ad3082f209582d”
Expires 响应过期的日期和时间 Expires: Thu, 01 Dec 2010 16:00:00 GMT
Last-Modified 请求资源的最后修改时间 Last-Modified: Tue, 15 Nov 2010 12:45:26 GMT
Location 用来重定向接收方到非请求URL的位置来完成请求或标识新的资源 Location: http://www.zcmhi.com/archives/94.html
Pragma 包括实现特定的指令,它可应用到响应链上的任何接收方 Pragma: no-cache
Proxy-Authenticate 它指出认证方案和可应用到代理的该URL上的参数 Proxy-Authenticate: Basic
refresh 应用于重定向或一个新的资源被创造,在5秒之后重定向(由网景提出,被大部分浏览器支持) Refresh: 5; url=http://www.zcmhi.com/archives/94.html
Retry-After 如果实体暂时不可取,通知客户端在指定时间之后再次尝试 Retry-After: 120
Server web服务器软件名称 Server: Apache/1.3.27 (Unix) (Red-Hat/Linux)
Set-Cookie 设置Http Cookie Set-Cookie: UserID=JohnDoe; Max-Age=3600; Version=1
Trailer 指出头域在分块传输编码的尾部存在 Trailer: Max-Forwards
Transfer-Encoding 文件传输编码 Transfer-Encoding:chunked
Vary 告诉下游代理是使用缓存响应还是从原始服务器请求 Vary: *
Via 告知代理客户端响应是通过哪里发送的 Via: 1.0 fred, 1.1 nowhere.com (Apache/1.1)
Warning 警告实体可能存在的问题 Warning: 199 Miscellaneous warning
WWW-Authenticate 表明客户端请求实体应该使用的授权方案 WWW-Authenticate: Basic

3.一个http请求的完整过程

当用户在浏览器输入www.taobao.com网址回车之后,网络协议都做了哪些工作呢?

  • 首先工作的是浏览器应用程序,他要解析出URL中域名。
  • 根据域名获取对应的ip地址,首先会去浏览器缓存中查看(可以在浏览器中输入chrome://net‐internals/#events 查看), 如果没有则从本机域名解析文件hosts(C:\Windows\System32\drivers\etc\hosts)中查看,还没有则从本地域名服务器、权威域名服务器、顶级域名服务器、根域名服务器(Root DNS Servers)层层解析。
  • 拿到IP地址后,浏览器就可以与服务器通过三次握手建立连接。
  • 握手建立之后,就开始组装http请求报文,发送报文 。
  • 服务器收到请求报文之后就开始对请求报文进行解析,之后生成响应数据,然后发送响应数据 。
  • 浏览器收到响应数据后,开始解析数据并渲染页面 。

过程图如下:
http,tcp,udp协议深度分析(硬核推荐)_第8张图片

4.通过火狐浏览器分析请求与响应报文

请求报文分析:

在浏览器中输入地址:http://localhost:8080/user/userLoginValidate?userName=admin&passWord=321 向我的tomcat服务器发送一个GET请求,其请求报文内容大致如下(注:GET请求的报文主体包含在URL中了):
http,tcp,udp协议深度分析(硬核推荐)_第9张图片
实际上,黑客就可以通过对请求行的请求方法和URL进行伪造(篡改),又或者对头部字段集合中的部分字段(如:Referer、User-Agent、Cookie)的Value进行伪造,达到欺骗服务器进而窃取数据的目的,诸如我在大学期间就通过伪造Cookie欺骗的投票系统的服务器,进而进行无限刷取票数。

响应报文分析:

刚刚请求的响应报文内容如下:
http,tcp,udp协议深度分析(硬核推荐)_第10张图片
上图只看到响应头的内容,没有响应体,这是由于火狐浏览器响应体需要在其他地方看:
http,tcp,udp协议深度分析(硬核推荐)_第11张图片
需要注意的地方,我一开始输入的密码是错误的,响应行的状态为200只能说明我这次的GET请求正常请求并返回响应结果了,不能说明密码正确。

三、TCP协议和UDP协议

1.UDP报文

UDP定义:Internet 协议集支持一个无连接的传输协议,该协议称为用户数据报协议(UDP,User Datagram Protocol)。UDP 为应用程序提供了一种无需建立连接就可以发送封装的 IP 数据包的方法。

UDP报文整体布局:

http,tcp,udp协议深度分析(硬核推荐)_第12张图片

UDP的首部格式(UDP头):

  • 源端口,发送方的端口
  • 目的端口,接收方的端口
  • 包长度,首部长度 + 用户数据包的长度(可以没有数据包,最小值为8)
  • 检验和,检查UDP用户数据传输中是否与错,有错就丢弃(检查首部长度和用户数据包)
    http,tcp,udp协议深度分析(硬核推荐)_第13张图片

UDP协议特点:

  • 无连接,传输数据时不需要建立连接,减小开销。
  • 尽最大努力交付,不确保可靠交付。
  • 面向报文。
  • 没有拥塞控制、确保信息实时性。
  • 支持一对一,一对多,多对一,多对多。
  • 首部开销小,只有8个字节。

2.TCP报文

TCP定义:传输控制协议(TCP,Transmission Control Protocol)是一种面向连接的、可靠的、基于字节流的传输层通信协议。

TCP报文整体布局:

http,tcp,udp协议深度分析(硬核推荐)_第14张图片

详细说明各个字段含义:

  • 16位源端口号:16位的源端口中包含初始化通信的端口。源端口和源IP地址的作用是标识报文的返回地址。

  • 16位目的端口号:16位的目的端口域定义传输的目的。这个端口指明报文接收计算机上的应用程序地址接口。

  • 32位序号:32位的序列号由接收端计算机使用,重新分段的报文成最初形式。当SYN出现,序列码实际上是初始序列码(Initial Sequence Number,ISN),而第一个数据字节是ISN+1。这个序列号(序列码)可用来补偿传输中的不一致。

  • 32位确认序号:32位的序列号由接收端计算机使用,重组分段的报文成最初形式。如果设置了ACK控制位,这个值表示一个准备接收的包的序列码。

  • 4位首部长度:4位包括TCP头大小,指示何处数据开始。

  • 保留(6位):6位值域,这些位必须是0。为了将来定义新的用途而保留。

  • 标志:6位标志域。表示为:紧急标志、有意义的应答标志、推、重置连接标志、同步序列号标志、完成发送数据标志。按照顺序排列是:URG、ACK、PSH、RST、SYN、FIN。

  • 16位窗口大小:用来表示想收到的每个TCP数据段的大小。TCP的流量控制由连接的每一端通过声明的窗口大小来提供。窗口大小为字节数,起始于确认序号字段指明的值,这个值是接收端正期望接收的字节。窗口大小是一个16字节字段,因而窗口大小最大为65535字节。

  • 16位校验和:16位TCP头。源机器基于数据内容计算一个数值,收信息机要与源机器数值 结果完全一样,从而证明数据的有效性。检验和覆盖了整个的TCP报文段:这是一个强制性的字段,一定是由发送端计算和存储,并由接收端进行验证的。

  • 16位紧急指针:指向后面是优先数据的字节,在URG标志设置了时才有效。如果URG标志没有被设置,紧急域作为填充。加快处理标示为紧急的数据段。

  • 选项:长度不定,但长度必须为1个字节。如果没有选项就表示这个1字节的域等于0。

  • 数据:该TCP协议包负载的数据。

在上述字段中,6位标志域的各个选项功能如下:

  • URG:紧急标志。紧急标志为"1"表明该位有效。
  • ACK:确认标志。仅当ACK=1时,确认号字段才有效。ACK=0时,确认号无效。
  • PSH:推标志。该标志置位时,接收端不将该数据进行队列处理,而是尽可能快地将数据转由应用处理。在处理Telnet或rlogin等交互模式的连接时,该标志总是置位的。
  • RST:复位标志。用于重置TCP连接。
  • SYN:同步标志。发起一个新连接,表明同步序列编号栏有效。当SYN=1,ACK=0时表示:这是一个连接请求报文段。若同意连接,则在响应报文段中使得SYN=1,ACK=1。因此,SYN=1表示这是一个连接请求,或连接接受报文。SYN这个标志位只有在TCP建产连接时才会被置1,握手完成后SYN标志位被置0。
  • FIN:结束标志。释放一个连接,FIN=1表示:此报文段的发送方的数据已经发送完毕,并要求释放传输连接。

注意:ACK、SYN和FIN这些大写的单词表示标志位,其值要么是1,要么是0;ack、seq小写的单词表示序号。

TCP协议特点:

  • 基于连接的:数据传输之前需要建立连接,数据传输之前都要建立连接(三次挥手),数据传输结束都要释放连接(四次挥手)。
  • 全双工的:双向传输(一端既可以做发送方也可以做接收方)。
  • 字节流:不限制数据大小,打包成报文段,保证有序接收,重复报文自动丢弃。
  • 流量缓冲:解决双方处理能力的不匹配。
  • 可靠的传输服务:保证可达,丢包时通过重发机制实现可靠性。
  • 拥塞控制:防止网络出现恶性拥塞。

3.TCP三次握手

三次握手过程分析

http,tcp,udp协议深度分析(硬核推荐)_第15张图片
握手之前客户端主动结束CLOSED阶段,被动打开的服务器端也结束CLOSED阶段,并进入LISTEN阶段。接下来开始"三次握手":
(1)第一次握手:客户端向服务端发送一段TCP报文,包含以下内容:

  • SYN(标志位,表示"请求建立新连接");
  • seq=x(序号为x);

随后客户端进入SYN-SENT阶段

(2)第二次握手:服务器端接收到来自客户端的TCP报文后,结束LISTEN阶段,并返回一段TCP报文,包含以下内容:

  • SYN和ACK(标志位,表示“确认客户端的报文seq序号有效,服务器能正常接收客户端发送的数据,并同意创建新连接”);
  • seq=y(序号为y);
  • ack=x+1(确认号为x+1,表示收到客户端的序号seq并将其值加1作为自己确认号ack的值);

随后服务器端进入SYN-RCVD阶段

(3)第三次握手:客户端接收到来自服务器端的确认收到数据的TCP报文之后,明确了从客户端到服务器的数据传输是正常的,结束SYN-SENT阶段。并返回最后一段TCP报文。包含以下内容:

  • ACK(标志位,表示“确认收到服务器端同意连接的信号”);
  • seq=x+1(序号为x+1,表示收到服务器端的确认号ack,并将其值作为自己的序号值);
  • ack=y+1(确认号为y+1,表示收到服务器端序号seq,并将其值加1作为自己的确认号ack的值);

随后客户端进入ESTABLISHED阶段
服务器端收到来自客户端的“确认收到服务器数据”的TCP报文之后,明确了从服务器端到客户端的数据传输是正常的。便结束SYN-RCVD阶段,也进入ESTABLISHED阶段。之后客户端和服务端就可以进行数据传输了,三次握手结束。

需要注意:从整个三次握手的过程来看,双方的确认号ack和序号seq的值,都是在前一次握手的基础上进行了计算,假如某一方发送的TCP报文出现了丢失就无法通过验证继续握手,这就保证了TCP报文传输的连续性。

接下来我们深挖一下服务端的Linux内核大致是如何处理TCP连接的:
图中部分参数说明:

  • tcp_max_syn_backlog是指定所能接受SYN同步包的最大客户端数量,即半连接上限;
  • somaxconn是指服务端所能accept即处理数据的最大客户端数量,即完成连接上限。

http,tcp,udp协议深度分析(硬核推荐)_第16张图片
大致过程:

  1. 内核会对某个端口进行监听;
  2. 当内核收到SYN请求连接报文的时候;
  3. SYN请求连接报文就会进入SYN队列中(该SYN队列由操作系统内核进行维护,进入SYN队列的报文状态会被设置为SYN_RCVD);
  4. 与此同时服务端内核立马会回一个带有SYN和ACK响应的报文给到客户端,随后进行等待;
  5. 直到客户端给服务端发送ACK响应报文;
  6. 此时会将SYN队列对应的请求报文出队,之后再入队到ACCEPT队列,这就表示三次握手结束,连接建立成功;
  7. 应用程序/网络程序就可以对ACCEPT队列进行监听,阻塞等待,当ACCEPT队列中有可用的连接后,就可以通过API拿到连接进行双向的数据通信

更多关于tcp_max_syn_backlogsomaxconn细节请查阅linux内核调优tcp_max_syn_backlog和somaxconn的区别

三次握手实践

想要测试三次握手的过程我们需要用到抓包工具,我这里就用netcat工具做演示:

  1. 首先我们通过网址:https://eternallybored.org/misc/netcat/下载netcat。

    http,tcp,udp协议深度分析(硬核推荐)_第17张图片

  2. 然后将下载后的压缩包解压后,找到nc.exe文件。
    http,tcp,udp协议深度分析(硬核推荐)_第18张图片

  3. 再将该文件复制粘贴到C盘 users/当前登录用户目录下即可,这样我们就可以通过cmd进入windows的命令界面使用nc命令了(简单粗暴的方式,也可以自己配置环境变量)。

  4. 在自己的测试服务器(我的是centos7)中打开一个测试端口,我这里使用的是8080,然后通过以下命令对服务器指定的端口号接收TCP报文情况进行监听:

    tcpdump -i eth0 -S -c 3  port 8080  
    //  tcpdum  -i  网卡号  -S[将相对序列号转化为绝对序列号]  -c  抓报文次数  port 监听端口号
    
  5. 在自己的windows电脑上通过cmd进入命令化界面,输入如下命令发送TCP请求(注意你通过nc命令发送TCP请求的端口号应该是你监听的端口号):

     nc 你服务器的IP地址 8080
    
  6. 然后在服务器中就会打印如下内容:
    http,tcp,udp协议深度分析(硬核推荐)_第19张图片其中:183.128.158.142.34718是客户端,cggeeker.webcache表示服务端。
    第一次握手是:183.128.158.142.34718 > cggeeker.webcache;
    第二次握手是:cggeeker.webcache > 183.128.158.142.34718;
    第三次握手是:183.128.158.142.34718 > cggeeker.webcache。

至此三次握手实践分析结束。

SYN攻击

  • 在三次握手过程中,Server发送SYN-ACK之后,收到Client的ACK之前的TCP连接称为半连接(half-open
    connect),此时Server处于SYN_RCVD状态,当收到ACK后,Server转入ESTABLISHED状态
  • SYN攻击就是Client在短时间内伪造大量不存在的IP地址,并向Server不断地发送SYN包,Server回复确认包,并等待Client的确认,由于源地址是不存在的,因此,Server需要不断重发直至超时,这些伪造的SYN包将产时间占用未连接队列,导致正常的SYN请求因为队列满而被丢弃,从而引起网络堵塞甚至系统瘫痪

http,tcp,udp协议深度分析(硬核推荐)_第20张图片
引用百度百科的图片方便读者理解SYN攻击过程

SYN攻击时一种典型的dos攻击,检测SYN攻击的方式非常简单,即当Server上有大量半连接状态且源IP地址是随机的,则可以断定遭到SYN攻击了,使用如下命令可以让之现行:

netstat -nap | grep SYN_RECV

4.TCP四次挥手

四次挥手过程分析

http,tcp,udp协议深度分析(硬核推荐)_第21张图片
挥手之前主动释放连接的客户端结束ESTABLISHED阶段。随后开始“四次挥手“:
(1)第一次挥手: 客户端想要释放连接,向服务器端发送一段TCP报文,包含以下内容:

  • FIN(标志位,表示”请求释放连接“);
  • seq=u(序号为u);

随后客户端进入FIN-WAIT-1阶段,即半关闭阶段。并且停止客户端到服务器端方向上发送数据(报文数据),但是客户端仍然能接收从服务器端传输过来的数据。

(2)第二次挥手: 服务器端接收到从客户端发出的TCP报文之后,确认了客户端想要释放连接,随后服务器端结束ESTABLISHED阶段,进入CLOSE-WAIT阶段(半关闭状态)并返回一段TCP报文,包含以下内容:

  • ACK(标志位,表示“接收到客户端发送的释放连接的请求”);
  • seq=v(序号为v);
  • ack=u+1(确认号为u+1,表示是在收到客户端报文的基础上,将其序号seq值加1作为本段报文确认号ack的值);

随后服务器端开始准备释放服务器端到客户端方向上的连接,但是这个过程中服务器端仍然可以向客户端发送未发送完的数据;客户端收到从服务器端发出的TCP报文之后,确认了服务器收到了客户端发出的释放连接请求,随后客户端结束FIN-WAIT-1阶段进入FIN-WAIT-2阶段

(3)第三次挥手: 服务器端自发出ACK确认报文后,经过了CLOSED-WAIT阶段,做好了释放服务器端到客户端方向上的连接准备,再次向客户端发出一段TCP报文,包含以下内容:

  • FIN和ACK,(标志位,表示“已经准备好释放连接了”,注意:这里的ACK并不是确认收到服务器端报文的确认报文);
  • seq=w(序号为w);
  • ack=u+1(确认号为u+1,表示是在收到客户端报文的基础上,将其序号seq值加1作为本段报文确认号ack的值)。

随后服务器端结束CLOSE-WAIT阶段进入LAST-ACK阶段,并且停止服务器端到客户端的方向上发送数据,但是服务器端仍然能够接收从客户端传输过来的数据(因为此刻两端都还没有完全关闭连接)。

(4)第四次挥手: 客户端收到从服务器端发出的TCP报文,确认了服务器端已做好释放连接的准备,结束FIN-WAIT-2阶段进入TIME-WAIT阶段,并向服务器端发送一段报文,包含以下内容:

  • ACK(标志位,表示“接收到服务器准备好释放连接的信号”)。
  • seq=u+1(序号为u+1,表示是在收到了服务器端报文的基础上,将其确认号ack值作为本段报文序号的值)。
  • ack=w+1(确认号为w+1,表示是在收到了服务器端报文的基础上,将其序号seq值加1作为本段报文确认号的值)。

随后客户端开始在TIME-WAIT阶段等待2MSL,服务器端收到从客户端发出的TCP报文之后结束LAST-ACK阶段进入CLOSED阶段由此正式确认关闭服务器端到客户端方向上的连接;

客户端等待完2MSL之后结束TIME-WAIT阶段进入CLOSED阶段,由此完成“四次挥手”。

需要注意:在客户端与服务器端传输的TCP报文中,双方的确认号ack和序号seq的值,都是在彼此ack和seq值的基础上进行计算的,这样做保证了TCP报文传输的连续性,一旦出现某一方发出的TCP报文丢失,便无法继续"挥手",以此确保了"四次挥手"的顺利完成

为什么“握手”是三次,“挥手”却要四次?(京东面试题)

  • 这是因为服务器端在LISTEN状态下,收到建立连接请求的SYN报文后,把ACK和SYN放在一个报文里发送给客户端。而关闭连接时,服务器端把ACK确认接收报文与FIN释放连接报文与是分别由第二次和第三次"握手"传输的。
  • 为啥挥手需要分两次发送呢?这是因为建立连接时,服务器端被动打开结束CLOSED阶段进入握手阶段并不需要任何准备,所以可以直接一次性返回带有ACK和SYN的报文;而释放连接时,服务器端突然收到客户端发来的释放连接的请求时,可能服务器端还在向客户端发送数据,还没发送完,所以并不能马上就释放掉连接,不然数据就丢失了,因此服务器端分了两步,先返回ACK确认我(服务器端)收到了客户端的报文,然后服务器端在CLOSE-WAIT阶段可以继续发送没有发送完的数据,当这个阶段结束后就返回FIN释放连接报文。

为什么客户端在TIME-WAIT阶段要等2MSL?(携程面试题)

原因如下:

  • 防止报文丢失,导致Server重复发送FIN:如果Client直接CLOSED了,那么由于IP协议的不可靠性或者是其它网络原因,导致Server没有收到Client最后回复的ACK。那么Server就会在超时之后继续发送FIN,此时由于Client已经CLOSED了,就找不到与重发的FIN对应的连接,最后Server就会收到RST而不是ACK,Server就会以为是连接错误把问题报告给高层。这样的情况虽然不会造成数据丢失,但是却导致TCP协议不符合可靠连接的要求。所以,Client不是直接进入CLOSED,而是要保持TIME-WAIT,当再次收到FIN的时候,能够保证对方收到ACK,最后正确的关闭连接。
  • 防止滞留在网络中的报文,对新建立的连接造成数据扰乱:如果Client直接CLOSED,然后又再向Server发起一个新连接,有可能新连接和老连接的端口号是相同的。一般来说不会发生什么问题,但是还是有特殊情况出现:假设新连接和已经关闭的老连接端口号是一样的,如果前一次连接的某些数据仍然滞留在网络中,这些延迟数据在建立新连接之后才到达Server,由于新连接和老连接的端口号是一样的,又因为TCP协议判断不同连接的依据是:IP地址+端口号,于是,TCP协议就认为那个延迟的数据是属于新连接的,这样就和真正的新连接的数据包发生混淆了。所以TCP连接还要在TIME-WAIT状态等待2倍MSL,这样可以保证本次连接的所有数据都从网络中消失。

5.面向字节流

  1. TCP是一种流协议(stream protocol)。这就意味着数据是以字节流的形式传递给接收者的,没有固有的”报文”或”报文边界”的概念。从这方面来说,读取TCP数据就像从串行端口读取数据一样–无法预先得知在一次指定的读调用中会返回多少字节(也就是说能知道总共要读多少,但是不知道具体某一次读多少)。
  2. TCP把应用交付的数据仅仅看成时一连串的无结构的字节流,TCP并不知道字节流的含义,TCP并不关心应用程序一次将多大的报文发送到TCP的缓存中,而是根据对方给出的发送窗口值当前网络拥堵的程度路径上的最大传输单元连接的输出队列中有多少数据来决定一个报文段应该包含多少个字节。

概念补充:
TCP最大段大小:Max Segment Size(MSS), TCP一次传输发送的最大数据段长度,默认536byte实际数据。

6.TCP拆包和粘包问题

拆包和粘包问题是处于网络比较底层的问题,在数据链路层、网络层以及传输层都有可能发生。

讨论TCP拆包和粘包问题前,我们不妨先来看看UDP是否会出现类似问题,我们可以从本文UDP报文整体布局那幅图中看出,在UDP首部采用了16bit来指示UDP数据报文的长度,因此在应用层能很好的将不同的数据报文区分开,从而避免粘包和拆包的问题。而TCP是基于字节流的,虽然应用层和TCP传输层之间的数据交互是大小不等的数据块,但是TCP把这些数据块仅仅看成一连串无结构的字节流,没有边界;同时从本文前面的TCP报文整体布局图也可以看出,在TCP的首部没有表示数据长度的字段,基于上面两点,在使用TCP传输数据时,才有粘包或者拆包现象发生的可能。

图解什么是拆包和粘包?

场景举例:客户端和服务端建立连接后,客户端连续给服务端发送两条数据后,客户端关闭与服务端的连接。

我们将可能出现的情况分类讨论如下:

  • 情况1:服务端一共读到两个数据包,第一个包包含客户端发出的第一条数据的完整信息,第二个包包含客户端发出的第二条数据,那这种情况比较好处理,服务端只需要简单的从网络缓冲区去读就好了,第一次读到第一条数据的完整信息,读完第一条数据后再从网络缓冲区将第二条数据完整读出来;
    http,tcp,udp协议深度分析(硬核推荐)_第22张图片
  • 情况2:服务端一共就读到一个数据包,这个数据包包含客户端发出的两条数据的完整信息,这个时候基于之前逻辑实现的服务端就会将这两条数据当作一条数据进行处理,因为服务端不知道第一条数据从哪儿结束和第二条数据从哪儿开始,这种情况其实是发生了TCP粘包;
    http,tcp,udp协议深度分析(硬核推荐)_第23张图片
  • 情况3:服务端一共收到了两个数据包,第一个数据包只包含了第一条数据的一部分,第一条数据的后半部分和第二条数据都在第二个数据包中,或者是第一个数据包包含了第一条数据的完整信息和第二条数据的一部分信息,第二个数据包包含了第二条数据的剩下部分,这种情况其实是发送了TCP拆包,因为发生了一条数据被拆分在两个包里面发送了,同样上面的服务器逻辑对于这种情况是不好处理;
    http,tcp,udp协议深度分析(硬核推荐)_第24张图片

为什么会发生TCP粘包、拆包呢?(知乎二面)

常见原因如下:

  1. 应用程序写入的数据大于套接字缓冲区大小,这将会发生拆包;
  2. 应用程序写入数据小于套接字缓冲区大小,网卡将应用多次写入的数据发送到网络上,这将会发生粘包;
  3. 进行MSS(最大报文长度)大小的TCP分段,当TCP报文长度-TCP头部长度>MSS的时候将发生拆包;
  4. 接收方法不及时读取套接字缓冲区数据,这将发生粘包。

如何处理粘包、拆包问题?(知乎二面)

通过上述分析可以知道解决粘包或拆包问题的关键在于指定数据的边界或者指定数据的长度,通常会有以下一些常见的解决办法:

  1. 使用带消息头的协议、消息头存储消息开始标识及消息长度信息,服务端获取消息头的时候解析出消息长度,然后向后读取该长度的内容;
  2. 设置定长消息,服务端每次读取既定长度的内容作为一条完整消息;
  3. 设置消息边界,服务端从网络流中按消息编辑分离出消息内容。

7.TCP异常情况

  • 进程终止: 进程终止会释放文件描述符, 仍然可以发送FIN. 和正常关闭没有什么区别。
  • 机器重启: 和进程终止的情况相同。
  • 机器掉电/网线断开: 接收端认为连接还在, 一旦接收端有写入操作,接收端发现连接已经不在了,,就会进行reset;即使没有写入操作,TCP自己也内置了一个保活定时器,会定期询问对方是否还在,如果对方不在,也会把连接释放。
  • 应用层的某些协议,也有一些这样的检测机制,例如HTTP长连接中,也会定期检测对方的状态;例如QQ, 在QQ断线之后,也会定期尝试重新连接。

总结

本篇文章先从网络分层原理开始讲解,对HTTP协议、TCP协议和UDP的报文布局进行对比和论述,其中对面试中经常问到的一个http请求的完整过程、tcp的三次握手和四次挥手过程以及tcp的拆包粘包问题进行深度探究,也用了一个小小的测试实验演示了tcp三次握手的过程;最后有关TCP协议实现数据可靠性传输(包括超时重传、流量控制、滑动窗口、延时应答)和HTTPS协议的加密通信原理(涉及摘要算法、加密算法、身份验证)等知识分享,请继续关注我后续的文章,持续更新中.......

你可能感兴趣的:(计算机网络,网络)