前言

最近笔者在实际项目开发中会频繁涉及到服务之间的远程调用、域名的配置和请求的转发等与计算机网络相关的知识。

这些其实在读本科和考研的时候都有学习过理论,但为了更透彻地掌握便于在工作中使用,我还是决定写一篇文章来分享实际开发中是怎么应用的。

下面将从 HTTP 协议的基本概念与简介、完整的请求过程、客户端的请求以及服务端的响应这四部分来展开,同时会使用实际的场景来加以分析,便于大家理解。


一、HTTP协议

1.1基本概念

HTTP 协议(Hyper Text Transfer Protocol)超文本传输协议,即传输文字、图片、音频、视频等超文本数据、是一种用于分布式、协作式和超媒体信息系统的应用层协议。为了更快地处理大量事务,确保协议的可伸缩性,HTTP 协议被设计成了一种无状态协议,不保留之前一切的请求或响应报文的信息。HTTP 协议也是万维网(WWW,World Wide Web)的数据通信的基础。

HTTP 是一个客户端(用户)和服务器端(网站)请求和应答的标准,其定义了定义 Web 客户端如何向 Web 服务器请求 Web 页面,以及服务器如何把 Web 页面响应给客户端。

HTTP 协议中并没有规定必须使用 TCP/IP 或其支持的层。事实上,HTTP 可以在任何互联网协议上,或其他网络上实现。HTTP 假定其下层协议提供可靠的传输。因此,任何能够提供这种保证的协议都可以被其使用,所以其在 TCP/IP 协议族使用 TCP 作为其传输层,而 UDP 是不可靠传输。

用户通过使用各种工具(如网页浏览器、网络爬虫或者 Jmeter 等)作为客户端,来发起一个 HTTP 请求到服务器的指定端口(默认为80)。这个客户端被称为用户代理程序(User Agent)。而接受并响应该 HTTP 请求的服务器上会存储着各种用户需要的资源,比如 HTML 文件和图像,这个被用户请求的服务器被称为源服务器(Origin Server)

1.2工作原理

通常,由 HTTP 客户端发起一个请求,创建一个到服务器指定端口(默认是80端口)的 TCP 连接,HTTP服务器则在那个端口监听客户端的请求。一旦收到请求,服务器会向客户端返回一个状态,比如"HTTP/1.1 200 OK",以及响应请求而返回的内容,如文件、错误消息、或者其它数据等。

以下是 HTTP 协议工作流程的几个关键步骤:

第一步:建立 TCP/IP 连接,客户端与服务器通过 Socket 三次握手进行连接

第二步:客户端向服务端发起 HTTP 请求,如:POST/login.html http/1.1

第三步:客户端发送请求头部、请求内容,最后会发送一空白行,标示客户端请求完毕

第四步:服务器做出应答,表示对于客户端请求的应答,如:HTTP/1.1 200 OK

第五步:服务器向客户端发送响应头部信息,发送一空白行,表示应答头信息发送完毕,随后以 Content-type 要求的数据格式,发送响应正文给客户端

第六步:服务端关闭 TCP 连接,如果服务器或者客户端的 Connection:keep-alive 则表示客户端与服务器端继续保存连接,在下次请求时可以继续使用这次的连接

二、请求过程

下面对 1.2 小节中的几个步骤做更为细致的讲解。

2.1域名解析

浏览器向 DNS 服务器请求解析该 URL 中的域名所对应的 IP 地址,查找过程依次如下:

  1. 浏览器缓存

    首先搜索浏览器自身的 DNS 缓存(缓存的时间比较短,大概只有1分钟,且只能容纳1000条缓存),看自身的缓存中是否是有域名对应且未过期的条目。如果有,则域名解析到此结束。

  2. 操作系统缓存

    如果上一步没有找到对应的条目,浏览器会搜索操作系统自身的 DNS 缓存,如果找到了没有过期的对应条目,则停止搜索,解析到此结束。查看操作系统自身的 DNS 缓存,以 Windows 系统为例,win + R 后输入 cmd 命令提示行,输入ipconfig /displaydns 进行查看。

  3. hosts 文件

    如果上一步没有找到对应条目,浏览器就会尝试读取操作系统本地的文件,以 Windows 系统为例:C:\Windows\System32\drivers\etc内的 hosts 文件。

  4. DNS 服务器

    如果以上的三步都没有找到对应条目,那么浏览器就会向 DNS 服务器请求进行域名解析。

    更具体地说,浏览器发起一个 DNS 的系统调用,向本地配置的首选 DNS 服务器(一般由运营商提供)发起域名解析请求。域名解析请求是通过 UDP 协议向DNS 的 53 端口发起请求,这个请求是递归的请求。也就是说,运营商的 DNS 服务器必须得提供给我们该域名的公网 IP 地址。

2.2TCP 连接

根据 DNS 服务器解析出的 IP 地址和默认端口号,与该服务器进行 TCP 连接中 3 次握手的前两次,来建立连接:

TCP 连接

2.3发送 HTTP 请求

即完成 TCP 的 3 次握手的第三次:

发送 HTTP 请求

2.4服务器应答

客户端发起了请求,服务器一定要有应答吗?要回答这个问题,得知道 HTTP 响应的底层原理是基于 HTTP 协议的通信机制,这个协议决定了:如果客户端发送的请求能准确到达服务器,那么服务器必须会有响应并返回。

在本文的第四章,我会拿一个部署在 Linux 服务器上的、基于Spring Boot 的 Java 程序来分析具体服务器是怎么做出响应的。

服务器应答

2.5响应内容

下面是访问 https://mvnrepository.com/ 即 Maven 远程中央仓库时,调用其搜索接口所产生的响应标头内容:

响应内容

2.6关闭连接

最后浏览器会关闭该 TCP 连接,浏览器利用自己内部的工作机制,把请求到的静态资源和 HTML 代码进行渲染,呈现给用户。


三、客户端请求

下面其实是本文的重头戏,会重点讲解具体的 HTTP 请求是怎么构建、发送请求的。

3.1请求Header

一个 HTTP 请求报文由请求行(request line)、请求头部(headers)、请求数据(request body)和空行(blank line)4个部分组成。

其中请求头部(headers)为请求报文添加了一些附加信息,由键值对组成,每行一对,名和值之间使用冒号分隔,如下图是由 PostMan 调用所示:

响应内容
请求 Header

常见的几个请求头释义:

常见请求头

且我们还可以自定义 Header 如:Authorization 是认证信息、Tenant-Code 是发起本次请求的租户编码。

注意:由于 HTTP 协议只规定 POST 提交的数据必须放在消息主体(body)中,并没有规定数据必须使用什么编码方式。服务端通常是根据请求头中的 Content-Type 字段来获知请求中的消息主体是用何种方式编码,再对 body 进行解析。

常用的 Content-Type 编码方式有:

  • application/x-www-form-urlencoded 数据在发送到服务器之前,会将表单内的数据转换为键值对,比如 username=admin&password=123456,并将所有字符都会进行 URL 转码;
  • multipart/form-data 数据将被编码为一条消息以标签为单元,用分隔符分开,既可以上传键值对,也可以上传文件,通常用于上传二进制的文件;
  • application/json 用来告诉服务端消息主体是序列化后的 JSON 字符串,前端无法将表单的 enctype 属性指定为 application/json,通常使用 Ajax 的方式发送这种编码形式的请求。

3.2请求方法

最常用的四种请求方法:GET、POST、PUT、DELETE。

常见 HTTP 请求方法

3.3cookie 和 token

在了解 Session 和 Cookies 之前,我们还需要了解 HTTP 的一个特点,叫作无状态。

HTTP 的无状态是指 HTTP 协议对事务处理是没有记忆能力的,也就是说服务器不知道客户端是什么状态。

这时两个用于保持 HTTP 连接状态的技术就出现了,它们分别是 Session 和 Cookie。

Session 在服务端,也就是网站的服务器,用来保存用户的 Session 信息。

Cookie 在客户端,也可以理解为浏览器端有了 Cookie,浏览器在下次访问网页时会自动附带上它发送给服务器,服务器通过识别 Cookie 并鉴定出是哪个用户,然后再判断用户是否是登录状态,进而返回对应的响应。


四、服务端响应

4.1demo 举例

这里以一个基于 Spring Boot 的 Java 程序来举例,@RequestMapping 是 Spring MVC 框架中的一个注解,它用于指示具体的 Controller 方法如何响应某个特定的请求。它可以用于将请求URL映射到控制器上,并可以指定不同的参数设置。

@RestController
@RequestMapping("/study")
public class StudyController { @Resource
private StudyService studyService; /**
* 新增
* @param studyDTO
* @return 是否成功
*/
@PostMapping("/add")
public BaseResponse<Boolean> addAwards(@RequestBody StudyDTO studyDTO) {
return ResultUtils.success(studyService.addStudy(studyDTO));
}
}

如果将这个应用部署在服务器上,你想访问到,那么需要在浏览器中输入:https://ip+port/服务名/study/add

我自己本地访问则是:http://localhost:28089/initial/study/add

4.2返回内容

那么 HTTP 返回的响应报文内容是什么?主要包括以下3个部分:

  • 响应状态行(Status Line):包含HTTP协议版本、响应状态码和状态消息。例如,HTTP/1.1 200 OK 表示 HTTP 协议版本是1.1,响应状态码是 200,状态消息是 OK。这个在下一节会单独拿出来讲。

  • 响应头部(Headers):包含了一系列的键值对,用来描述响应的属性和元数据。常见的响应头包括 Content-Type(指定响应的数据类型)、Content-Length(指定响应体的长度)等。HTTP 协议定义了许多标准的响应头,不同的头部字段有不同的作用。

    以下是一些常见的响应头:

    • Content-Type:指定响应体的数据类型。例如,Content-Type: text/html 表示响应体是 HTML 文档。

    • Content-Length:指定响应体的长度,以字节为单位。例如,Content-Length: 1024 表示响应体的长度是 1024 字节。

    • Location:用于重定向客户端到新的URL。例如,Location: http://example.com/new_page 会将客户端重定向到 http://example.com/new_page。

    • Set-Cookie:用于设置 Cookie,可以在响应中向客户端发送 Cookie 信息。

    • Cache-Control:控制响应的缓存行为,包括缓存的过期时间、验证方式等。

    • Server:指定响应的服务器信息。例如,Server: Apache/2.4.38 表示响应是由 Apache 服务器版本 2.4.38 生成的。

  • 响应体(Body):包含了实际的响应数据,可以是HTML页面、JSON数据、文本等。响应体的格式由Content-Type头部字段指定。

    以下是一些常见的Content-Type值:

    • text/html:HTML 文档。

    • application/json:JSON 数据。

    • text/plain:纯文本。

    • image/jpeg:JPEG图像。

    • application/xml:XML 数据。

4.3返回状态码

以下是一些常见的HTTP响应状态码:

常见 HTTP 响应状态码


五、文章小结

无论是前端还是后端,不论是科班还是非科班,也无论是开发、测试还是产品,了解和掌握 HTTP 请求的一些基本知识都是非常重要的。它是现代互联网中不可或缺的一部分,为我们提供了高效、灵活、可靠的数据传输方式,为 Web 应用程序的开发和使用提供了强有力的支持。

今天的分享就到这里,如有不足和错误,还请大家指正。或者你有其它想说的,也欢迎大家在评论区交流!

参考文档:

https://blog.csdn.net/u010804417/article/details/123638124

https://www.cnblogs.com/engeng/articles/5959335.html

【进阶篇】一文搞清楚网页发起 HTTP 请求调用的完整过程的更多相关文章

  1. 基础篇|一文搞懂RNN(循环神经网络)

    基础篇|一文搞懂RNN(循环神经网络) https://mp.weixin.qq.com/s/va1gmavl2ZESgnM7biORQg 神经网络基础 神经网络可以当做是能够拟合任意函数的黑盒子,只 ...

  2. C# 30分钟完成百度人脸识别——进阶篇(文末附源码)

    距离上次入门篇时隔两个月才出这进阶篇,小编惭愧,对不住关注我的卡哇伊的小伙伴们,为此小编用这篇博来谢罪. 前面的准备工作我就不说了,注册百度账号api,创建web网站项目,引入动态链接库引入. 不了解 ...

  3. C#发起Http请求,调用接口

    //方法1. Post 异步请求,普通的异步请求,传输普通的字符串等,对于有html代码的字段值的传输支持不好,如果需要传输html,二进制等数据的传输,请使用下面第二个方法,即使用UploadDat ...

  4. Hadoop系列番外篇之一文搞懂Hadoop RPC框架及细节实现

    @ 目录 Hadoop RPC 框架解析 1.Hadoop RPC框架概述 1.1 RPC框架特点 1.2 Hadoop RPC框架 2.Java基础知识回顾 2.1 Java反射机制与动态代理 2. ...

  5. 利用jmeter发起java请求调用shell脚本

    1.创建maven项目 在pom文件中加入依赖:     2.在路径src/main/java下创建类,如类名shellclass                     3.      创建jmet ...

  6. Spring+SpringMVC+MyBatis+easyUI整合进阶篇(十五)阶段总结

    作者:13 GitHub:https://github.com/ZHENFENG13 版权声明:本文为原创文章,未经允许不得转载. 一 每个阶段在结尾时都会有一个阶段总结,在<SSM整合基础篇& ...

  7. Spring+SpringMVC+MyBatis+easyUI整合进阶篇(六)一定要RESTful吗?

    作者:13 GitHub:https://github.com/ZHENFENG13 版权声明:本文为原创文章,未经允许不得转载. 写在前面的话 这个问题看起来就显得有些萌,或者说类似的问题都有些不靠 ...

  8. 《JavaScript网页特效经典300例-进阶篇》

    <Javascript网页经典特性300例> 进阶篇 第11章:导航菜单特效 二级导航菜单三级导航菜单动态加载导航菜单三级联动导航菜单树形导航菜单当网页超过一屏时导航菜单始终置顶 第12章 ...

  9. Web端即时通讯基础知识补课:一文搞懂跨域的所有问题!

    本文原作者: Wizey,作者博客:http://wenshixin.gitee.io,即时通讯网收录时有改动,感谢原作者的无私分享. 1.引言 典型的Web端即时通讯技术应用场景,主要有以下两种形式 ...

  10. idea 插件的使用 进阶篇

    CSDN 2016博客之星评选结果公布    [系列直播]零基础学习微信小程序!      "我的2016"主题征文活动   博客的神秘功能 idea 插件的使用 进阶篇(个人收集 ...

随机推荐

  1. JDK源码阅读-------自学笔记(十四)(java.util.Calendar日历类)

    Calendar 提供了关于日期计算的相关功能,比如:年.月.日.时.分.秒的展示和计算. GregorianCalendar 是 Calendar 的一个具体子类,提供了世界上大多数国家/地区使用的 ...

  2. WPF,Frame控件的一个BUG

    我使用WPF默认的frame <Frame Style="{DynamicResource FrameStyle1}" x:Name="frame" He ...

  3. Docker Build Cache 缓存清理

    Docker 18.09 引入了 BuildKit ,提升了构建过程的性能.安全.存储管理等能力. docker system df 命令,类似于 Linux上的 df 命令,用于查看 Docker ...

  4. 【web】自定义协议Protocol URL

    URL Protocol(自定义协议)可以让web页面调用本地exe程序,这个神奇的功能是怎么实现的呢? URL ProtocolURL Protocol,没错就是标题里所说的自定义协议.这玩意儿大家 ...

  5. c语言不可不说的一件事——进制之间的转化

    进制之间的转换 二进制转换 二进制转换为十进制 10111010.101 转换方法: 个位数是乘以2的0次方 从小数点开始分割,(小数点前从右往左,小数点后从左往右)乘以2的对应次方(从0开始取),最 ...

  6. 获取某一个数的2进制位数以及bitmask

    举例说明:比如32对应的2进制为2b'100000,对应的bitmask为2b'11111. 实现代码: #include <stdio.h> typedef unsigned char ...

  7. mongodb常用数据库指令

    通过客户端的命令进入到mongodb服务中 mongo命令进入客户端 show dbs  查看数据库 show tables/show collections 查看集合(查看当前库里面的表) db 查 ...

  8. linux系统下,搭建kafka环境(单机版)

    安装前准备: 安装JDK 安装zookeeper(如果使用kafka内置的zookeeper,可以忽略) 第一步.安装JDK kafka依赖JAVA环境,所以首先要安装jdk 第二步.安装zookee ...

  9. docker-20.10.24搭建ferry工单系统

    安装文档 https://www.fdevops.com/docs/ferry-tutorial-document/introduction 必须要有docker环境,19.03以上的 本文档需用户自 ...

  10. star 最多的 Go 语言本地化库|GitHub 2.8K

    如果你是一位 Go 用户,可以在我开源的学习仓库中,找到针对各种往期归档文章,及学习资料. B站:白泽talk,公众号[白泽talk],回复"电子书",即可获得包含<100个 ...