HTTP请求过程 常见协议 请求类型 状态码 websocket

HTTP(HyperText Transfer Protocol)超文本传输协议,是一种用于分布式、协作式和超媒体信息系统的应用层协议。
HTTP 是一个简单的请求-响应协议,是客户端和服务端之间请求和应答的标准,它通常运行在 TCP(传输控制协议)之上由统一资源标识符(Uniform Resource Identifiers,URI 包含 URL 和 URN )来标识

HTTP 通过使用浏览器、网络爬虫或者其它的工具,客户端发起一个HTTP请求到服务器上指定端口。它指定了客户端可能发送给服务器什么样的消息以及得到什么样的响应。HTTP是万维网的数据通信的基础。
简单来说:
浏览器进行DNS域名解析,得到对应的IP地址
根据这个IP,找到对应的服务器建立连接(三次握手)
建立TCP连接后发起HTTP请求(一个完整的http请求报文)
服务器响应HTTP请求,浏览器得到html代码(服务器如何响应)
浏览器解析html代码,并请求html代码中的资源(如js、css、图片等)
浏览器对页面进行渲染呈现给用户
服务器关闭TCP连接(四次挥手)

0、URL匹配和DNS解析:

之前在简述 URL 中说过,当我们在浏览器中输入一段 URL 的时候,会通过一系列规则,匹配到相应的唯一资源,比如说:http://abc.cn/example/index.html,则是告诉浏览器,我们需要通过http协议,在abc.cn这个服务端,在默认的80端口下,在/example目录下,请求index.html这个资源。

不过其实大家都不认这个域名,认的都是abc.cn对应的IP地址.
就像我知道你叫张三,但是能表明你身份的不是张三这个名字,而是你的身份证号码一样,域名的出现只是为了方便人们记忆和使用,但要让计算机识别,还需要通过DNS将域名解析到相应的IP地址。

首先会搜索浏览器自身的DNS缓存(缓存时间比较短,大概只有1分钟,且只能容纳1000条缓存)
如果浏览器自身的缓存里面没有找到,那么浏览器会搜索系统自身的DNS缓存
如果还没有找到,那么尝试从 hosts文件里面去找
在前面三个过程都没获取到的情况下,浏览器就会发起一个DNS的系统调用,就会向本地配置的首选DNS服务器(一般是电信运营商提供的,也可以使用像Google提供的DNS服务器)发起域名解析请求(通过的是UDP协议向DNS的53端口发起请求,这个请求是递归的请求,也就是运营商的DNS服务器必须得提供给我们该域名的IP地址)

1、建立TCP连接:三次握手

HTTP是应用层协议,他的工作还需要数据层协议的支持,最常与它搭配的就是TCP协议(应用层、数据层是OSI七层模型中的,以后有机会会说到的)。TCP协议称为数据传输协议,是可靠传输,面向连接的,并且面向字节流的。

面向连接:通信之前先建立连接,确保双方在线。

可靠传输:在网络正常的情况下,数据不会丢失。

面向字节流:传输灵活,但是TCP的传输存在粘包问题,没有明显的数据约定。

在正式发送请求之前,需要先建立TCP连接。建立TCP连接的过程简单地来说就是客户端和服务端之间发送三次消息来确保连接的建立,这个过程称为三次握手。
第一次握手:建立连接。客户端发送连接请求报文段,将SYN位置为1,Sequence Number为x;然后,客户端进入SYN_SEND状态,等待服务器的确认;

第二次握手:服务器收到SYN报文段。服务器收到客户端的SYN报文段,需要对这个SYN报文段进行确认,设置Acknowledgment Number为x+1(Sequence Number+1);同时,自己自己还要发送SYN请求信息,将SYN位置为1,Sequence Number为y;服务器端将上述所有信息放到一个报文段(即SYN+ACK报文段)中,一并发送给客户端,此时服务器进入SYN_RECV状态;

第三次握手:客户端收到服务器的SYN+ACK报文段。然后将Acknowledgment Number设置为y+1,向服务器发送ACK报文段,这个报文段发送完毕以后,客户端和服务器端都进入ESTABLISHED状态,完成TCP三次握手。
原因:了防止已失效的连接请求报文段突然又传送到了服务端,因而产生错误。

2、发送请求

TCP连接建立完毕之后,客户端就可以向服务端发送请求报文来请求资源了。请求报文分为请求行、请求头、空行和请求体,服务端通过请求行和请求头中的内容获取客户端的信息,通过请求体中的内容获取客户端传过来的数据。

3、响应应答

在接收到客户端发来的请求报文并且确认完毕之后,服务端会向客户端发送响应报文。响应报文由状态行、响应头、空行和响应体组成,服务端通过状态行和响应头告诉客户端请求的状态和如何对数据处理等信息,真正的数据则在响应体中传输给客户端。

4、断开TCP连接

当请求完成后,还需断开TCP连接。断开的过程简单地说就算客户端和服务端之间发送四次信息来确保连接的断开,所以称为四次挥手。
在这里插入图片描述

以上就是一个HTTP请求的简单过程了,接来下再说一说HTTP请求的特性。

一、单向请求

HTTP请求是单向的,是只能由客户端发起请求,由服务端响应的请求-响应模式。(如果你需要双向请求,可以用socket)

二、基于TCP协议

HTTP是应用层协议,所以其数据传输部分是基于TCP协议实现的。

三、无状态

HTTP请求是无状态的,即没有记忆功能,不能获取之前请求或响应的内容。起初这种简单的模式,能够加快处理速度,保证协议的稳定,但是随着应用的发展,这种无状态的模式会使我们的业务实现变得麻烦,比如说需要保存用户的登录状态,就得专门使用数据库来实现。于是乎,为了实现状态的保持,引入了Cookie技术来管理状态。

四、无连接

HTTP协议不能保存连接状态,每次连接只处理一个请求,用完即断,从而达到节约传输时间、提高并发性。在TCP连接断开之后,客户端和服务端就像陌生人一样,下次再发送请求,就得重新建立连接了。有时候,当我们需要发送一段频繁的请求时,这种无连接的状态反而会耗费更多的请求时间(因为建立和断开连接本身也需要时间),于是乎,HTTP1.1中提出了持久连接的概念,可以在请求头中设置Connection: keep-alive来实现。

常见协议
http1.0 1.1 1.2 2 3
HTTP默认端口号为80。它也可以承载在TLS和SSL之上,通过加密、认证的方式实现数据传输的安全,称为HTTPS,HTTPS默认端口号为443。

HTTP/0.9:1991年发布,极其简单,只有一个get命令
HTTP/1.0:1996年5月发布,增加了大量内容
HTTP/1.1:1997年1月发布,进一步完善HTTP协议,是目前最流行的版本
SPDY :2009年谷歌发布SPDY协议,主要解决HTTP/1.1效率不高的问题
HTTP/2 :2015年借鉴SPDY的HTTP/2发布.

.HTTP/1.0和1.1的区别
1 缓存处理:HTTP/1.0 使用 Pragma:no-cache + Last-Modified/If-Modified-Since来作为缓存判断的标准;HTTP/1.1 引入了更多的缓存控制策略:Cache-Control、Etag/If-None-Match等
2 状态管理:HTTP/1.1新增了24个错误状态响应码,如409(Conflict)表示请求的资源与资源的当前状态发生冲突;410(Gone)表示服务器上的某个资源被永久性的删除。
3 范围请求:HTTP/1.1在请求头引入了range头域,它允许只请求资源的某个部分,即返回码是206(Partial Content),这样就方便了开发者自由的选择以便于充分利用带宽和连接,支持断点续传
4 Host头:HTTP1.0中认为每台服务器都绑定一个唯一的IP地址,因此,请求消息中的URL并没有传递主机名(hostname)。但随着虚拟主机技术的发展,在一台物理服务器上可以存在多个虚拟主机(Multi-homed Web Servers),并且它们共享一个IP地址。HTTP1.1的请求消息和响应消息都应支持Host头域,且请求消息中如果没有Host头域会报告一个错误(400 Bad Request)。有了Host字段,就可以将请求发往同一台服务器上的不同网站,为虚拟主机的兴起打下了基础
5 持久连接:HTTP/1.1 最大的变化就是引入了持久连接(persistent connection),在HTTP/1.1中默认开启 Connection: keep-alive,即TCP连接默认不关闭,可以被多个请求复用,提高效率。
注意的是:缺点也有:HTTP/1.1 的持久连接和管道机制允许复用TCP连接,在一个TCP连接中,也可以同时发送多个请求,但是所有的数据通信都是按次序完成的,服务器只有处理完一个回应,才会处理下一个回应。比如客户端需要A、B两个资源,管道机制允许浏览器同时发出A请求和B请求,但服务器还是按照顺序,先回应A请求,完成后再回应B请求,这样如果前面的回应特别慢,后面就会有很多请求排队等着,这称为"队头阻塞

HTTP/2协议只在HTTPS环境下才有效,升级到HTTP/2,必须先启用HTTPS。HTTP/2解决了HTTP/1.1的性能问题,主要特点如下:

  1. 二进制分帧:HTTP/1.1的头信息是文本(ASCII编码),数据体可以是文本,也可以是二进制;HTTP/2 头信息和数据体都是二进制,统称为“帧”:头信息帧和数据帧;
  2. 多路复用(双工通信):通过单一的 HTTP/2 连接发起多重的请求-响应消息,即在一个连接里,客户端和浏览器都可以同时发送多个请求和响应,而不用按照顺序一一对应,这样避免了“队头堵塞
  3. 数据流:因为 HTTP/2 的数据包是不按顺序发送的,同一个连接里面连续的数据包,可能属于不同的回应。因此,必须要对数据包做标记,指出它属于哪个回应。
  4. 头部压缩:HTTP 协议不带有状态,每次请求都必须附上所有信息。所以,请求的很多字段都是重复的,,一模一样的内容,每次请求都必须附带,这会浪费很多带宽,也影响速度。HTTP/2 对这一点做了优化,引入了头信息压缩机制(header compression)。一方面,头信息压缩后再发送(SPDY 使用的是通用的DEFLATE 算法,而 HTTP/2 则使用了专门为首部压缩而设计的 HPACK 算法)。;另一方面,客户端和服务器同时维护一张头信息表,所有字段都会存入这个表,生成一个索引号,以后就不发送同样字段了,只发送索引号,这样就提高速度了
  5. 服务端推送:HTTP/2 允许服务器未经请求,主动向客户端发送资源,这叫做服务器推送。服务器可以预期到客户端请求网页后,很可能会再请求静态资源,所以就主动把这些静态资源随着网页一起发给客户端了。

HTTPS特点
缓存:只要在HTTP头中使用特定命令,就可以缓存HTTPS;延迟:HTTP耗时 = TCP握手;HTTPS耗时 = TCP握手 + SSL握手。SSL握手耗时大概是TCP握手耗时的三倍左右。

HTTP请求类型:
get?post?delete?
在这里插入图片描述
OPTIONS:返回服务器针对特定资源所支持的HTTP请求方法。也可以利用向Web服务器发送’*'的请求来测试服务器的功能性。
HEAD:向服务器索要与GET请求相一致的响应,只不过响应体将不会被返回。这一方法可以在不必传输整个响应内容的情况下,就可以获取包含在响应消息头中的元信息。
GET:向特定的资源发出请求。
POST:向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。POST请求可能会导致新的资源的创建和/或已有资源的修改。
PUT:向指定资源位置上传其最新内容。
DELETE:请求服务器删除 Request-URI 所标识的资源。
TRACE:回显服务器收到的请求,主要用于测试或诊断。
CONNECT:HTTP/1.1 协议中预留给能够将连接改为管道方式的代理服务器。

虽然 HTTP 的请求方式有 8 种,但是我们在实际上常用的也就是 get 和 post,其他请求方式也都可以通过这两种方式间接的来实现。

GET - 从指定的资源请求数据。
POST - 向指定的资源提交要被处理的数据

请注意,查询字符串(名称/值对)是在 GET 请求的 URL 中发送的:

/test/demo_form.asp?name1=value1&name2=value2

有关 GET 请求的其他一些注释:

GET 请求可被缓存
GET 请求保留在浏览器历史记录
GET 请求可被收藏为书签
GET 请求不应在处理敏感数据时使用
GET 请求有长度限制
GET 请求只应当用于取回数据

POST 方法
请注意,查询字符串(名称/值对)是在 POST 请求的 HTTP 消息主体中发送的:

POST /test/demo_form.asp HTTP/1.1
Host: w3schools.com
name1=value1&name2=value2

有关 POST 请求的其他一些注释:

POST 请求不会被缓存
POST 请求不会保留在浏览器历史记录
POST 不能被收藏为书签
POST 请求对数据长度没有要求

那么 ,面试又该怎么说?

(1)post更安全(不会作为url的一部分,不会被缓存、保存在服务器日志、以及浏览器浏览记录中)

(2)post发送的数据更大(get有url长度限制)

(3)post能发送更多的数据类型(get只能发送ASCII字符)

(4)post比get慢

(5)post用于修改和写入数据,
get一般用于搜索排序和筛选之类的操作目的是资源的获取,读取数据

(6)GET回退浏览器无害,POST会再次提交请求。
两者之间没有本质区别,区别就在于数据存储的位置。各自有适用环境,根据需求选择合适的方法即可
其实post请求和get请求都是HTTP的请求方式,
本质上来说并无区别,底层实现都是基于TCP/IP协议。

但是请求有各种各样的方式,于是HTTP对请求方式进行了划分和规定,于是产生了get、post处理请求的分工和区别。

此外搜索到另外一个区别:GET产生一个TCP数据包;POST产生两个TCP数据包。

对于GET方式的请求,浏览器会把http header和data一并发送出去,服务器响应200(返回数据);

而对于POST,浏览器先发送header,服务器响应100 continue,浏览器再发送data,服务器响应200 ok(返回数据)。

  1. GET与POST都有自己的语义,不能随便混用。

  2. 据研究,在网络环境好的情况下,发一次包的时间和发两次包的时间差别基本可以无视。而在网络环境差的情况下,两次包的TCP在验证数据包完整性上,有非常大的优点。

  3. 并不是所有浏览器都会在POST中发送两次包,Firefox就只发送一次。

常见状态码:

HTTP状态码,即HTTP协议状态码,是我们访问网站时会遇到的,服务器端返回的Http响应码,不同的数字分别代表着不同的响应状态。
1、 HTTP Status Code 1xx 请求信息
这一组状态码表明这是一个临时性响应。此响应仅由状态行和可选的HTTP头组成,以一个空行结尾。由于HTTP/1.0未定义任何1xx状态码,所以不要向HTTP/1.0客户端发送1xx响应。
在这里插入图片描述
2.HTTP Status Code 2xx 成功状态
这一组状态码表明客户端的请求已经被服务器端成功接收并正确解析。
在这里插入图片描述
3.HTTP Status Code 3xx 重定向状态
这一组状态码表示客户端需要采取更进一步的行动来完成请求。通常,这些状态码用来重定向,后续的请求地址(重定向目标)在本次响应的Location域中指明。
在这里插入图片描述
4.HTTP Status Code 4xx 客户端错误
这一组状态码表示客户端的请求存在错误,导致服务器无法处理。除非响应的是一个HEAD请求,否则服务器就应该返回一个解释当前错误状况的实体,以及这是临时的还是永久性的状况。
在这里插入图片描述
5.HTTP Status Code 5xx 服务器错误状态
这一组状态码说明服务器在处理请求的过程中有错误或者异常状态发生,也有可能是服务器意识到以当前的软硬件资源无法完成对请求的处理。在这里插入图片描述

enmm
简单来说的话,日常生活比较多的是:
下面是常见的 HTTP 状态码:

200 - 请求成功
301 - 资源(网页等)被永久转移到其它URL
404 - 请求的资源(网页等)不存在
500 - 内部服务器错误。

最后的websockert

我们已经有了 HTTP 协议,为什么还需要另一个协议?它能带来什么好处?

答案很简单,因为 HTTP 协议有一个缺陷:通信只能由客户端发起。

服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息,是真正的双向平等对话,属于服务器推送技术的一种。

WebSocket和HTTP都是基于TCP协议的两个不同的协议
WebSocket依赖于HTTP连接

那么就有这些问题,
WebSocket依赖于HTTP连接,那么它如何从连接的HTTP协议转化为WebSocket协议?

每个WebSocket连接都始于一个HTTP请求。具体来说,WebSocket协议在第一次握手连接时,通过HTTP协议在传送WebSocket支持的版本号,协议的字版本号,原始地址,主机地址等等一些列字段给服务器端:

GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key:dGhlIHNhbXBsZSBub25jZQ==
Origin: http://example.com
Sec-WebSocket-Version: 13

注意,关键的地方是,这里面有个Upgrade首部,用来把当前的HTTP请求升级到WebSocket协议,这是HTTP协议本身的内容,是为了扩展支持其他的通讯协议。如果服务器支持新的协议,则必须返回101:

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept:s3pPLMBiTxaQ9kYGzzhZRbK+xOo=

在这里插入图片描述

WebSocket为什么要依赖于HTTP协议的连接?
WebSocket设计上就是天生为HTTP增强通信(全双工通信等),所以在HTTP协议连接的基础上是很自然的一件事,并因此而能获得HTTP的诸多便利。第二,这诸多便利中有一条很重要,基于HTTP连接将获得最大的一个兼容支持,比如即使服务器不支持WebSocket也能建立HTTP通信,只不过返回的是onerror而已,这显然比服务器无响应要好的多。

其特点:
(1)建立在 TCP 协议之上,服务器端的实现比较容易。

(2)与 HTTP 协议有着良好的兼容性。默认端口也是80和443,并且握手阶段采用 HTTP 协议,因此握手时不容易屏蔽,能通过各种 HTTP 代理服务器。

(3)数据格式比较轻量,性能开销小,通信高效。

(4)可以发送文本,也可以发送二进制数据。

(5)没有同源限制,客户端可以与任意服务器通信。

(6)协议标识符是ws(如果加密,则为wss),服务器网址就是 URL。

在这里插入图片描述
Spring 对于 WebSocket 的支持基于下面的 jar 包:

<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-websocket</artifactId>
  <version>${spring.version}</version>
</dependency>

在 Spring 实现 WebSocket 服务器大概分为以下几步:

创建 WebSocket 处理器

扩展 TextWebSocketHandler 或 BinaryWebSocketHandler ,你可以覆写指定的方法。Spring 在收到 WebSocket 事件时,会自动调用事件对应的方法。


import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.TextMessage;

public class MyHandler extends TextWebSocketHandler {

    @Override
    public void handleTextMessage(WebSocketSession session, TextMessage message) {
        // ...
    }

}
WebSocketHandler 源码如下,这意味着你的处理器大概可以处理哪些 WebSocket 事件:

public interface WebSocketHandler {

   /**
    * 建立连接后触发的回调
    */
   void afterConnectionEstablished(WebSocketSession session) throws Exception;

   /**
    * 收到消息时触发的回调
    */
   void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception;

   /**
    * 传输消息出错时触发的回调
    */
   void handleTransportError(WebSocketSession session, Throwable exception) throws Exception;

   /**
    * 断开连接后触发的回调
    */
   void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception;

   /**
    * 是否处理分片消息
    */
   boolean supportsPartialMessages();

}
配置 WebSocket

配置有两种方式:注解和 xml 。其作用就是将 WebSocket 处理器添加到注册中心。

实现 WebSocketConfigurer
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;

@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {

@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
    registry.addHandler(myHandler(), "/myHandler");
}

@Bean
public WebSocketHandler myHandler() {
    return new MyHandler();
}

}


xml 方式
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:websocket="http://www.springframework.org/schema/websocket"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/websocket
        http://www.springframework.org/schema/websocket/spring-websocket.xsd">

    <websocket:handlers>
        <websocket:mapping path="/myHandler" handler="myHandler"/>
    </websocket:handlers>

    <bean id="myHandler" class="org.springframework.samples.MyHandler"/>

</beans>

Node.js
常用的 Node 实现有以下三种。

µWebSockets
Socket.IO
WebSocket-Node
  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值