TCP、HTTP协议HTTP请求完整过程(附TCP工作方式)

538 阅读14分钟

我所整理的东西都是曾经看视频,帖子,或者某个大佬说的话最后写成的笔记。现在相当于把笔记重新整理成一篇文章。所以哪怕有一些引用也找不到出处了,就不标明了!

什么是HTTP协议?

HTTP协议是超文本传输协议(默认端口80)。
服务器传输超文本到本地浏览器的传送协议。
HTTP是一个基于TCP/IP通信协议来传送数据的。
HTTP就是客服端→服务端的数据传输。
大致工作流程:
(1)客户与服务器建立连接;
(2)客户向服务器提出请求;
(3)服务器接受请求,并根据请求返回相应的文件作为应答;
(4)客户与服务器关闭连接。

HTTP的特征:

1. 无连接(HTTP 的设计者有意利用这种特点将协议设计为请求时建连接、请求完释放连接,以尽快将资源释放出来服务其他客户端。)。
正常默认是短链接:建立连接→传送数据→关闭连接。
但是随着发展,发现有时候每次访问都需要建立一次 TCP 连接就显得很低效。后来,Keep-Alive 被提出用来解决这效率低的问题。就是长连接
可以设置为长连接:建立连接→传送数据→传送数据→...→关闭连接。
其实长连接还分为两种(完全理论知识,我没实际操作过。视频里讲的):

  • without pipdining:收到上一个请求响应后才能发下一个。
  • with pipdining:不管响没响应,都可以再发请求。

长短连接的优缺点:
像WEB网站的http服务一般都用短链接,因为长连接对于服务端来说会耗费一定的资源,而像WEB网站这么频繁的成千上万甚至上亿客户端的连接用短连接会更省一些资源,如果用长连接,而且同时有成千上万的用户,如果每个用户都占用一个连接的话,那可想而知吧。所以并发量大,但每个用户无需频繁操作情况下需用短连好。

长连接是为了节省每次请求都要建立新连接所需要的时间,还节约带宽。多用于操作频繁,点对点的通讯,而且连接数不能太多情况。每个TCP连接都需要三步握手,这需要时间,如果每个操作都是先连接,再操作的话那么处理速度会降低很多,所以每个操作完后都不断开,次处理时直接发送数据包就OK了,不用建立TCP连接。例如:数据库的连接用长连接, 如果用短连接频繁的通信会造成socket错误,而且频繁的socket 创建也是对资源的浪费。
2. HTTP是媒体独立的(不同的地方有不同的说法,我这里按照视频里讲解的说了。我也在别的地方看到的http特点不是这么讲的,别较真)。
因为tcp传输的是报文段,所以任何类型都可以传输。只要客户端和服务端达成一致即可。
3. HTTP是无状态的(这个无连接和无状态是统一说法,没啥好撕的)。
通俗一点的理解就是:啥也不记。
优缺点都有:缺点是如果需要之前的数据必须重新传,比较麻烦。但是如果不需要数据则正好,应答较快。
这里有一点要注意:HTTP 是一个无状态协议,这意味着每个请求都是独立的,Keep-Alive 没能改变这个结果。所以我们所谓的长连接只不过不用每次新建连接,但是每一次的请求还是独立的。
这些就是我之前在视频里看到的并且总结的知识点。然后因为写这篇文章所以还额外找了一些资料。看到了另一种关于http特征的说法,在这里粘贴一下,文章的最后我会贴上参考链接的。

HTTP协议的主要特点可概括如下:
1.支持客户/服务器模式。
2.简单快速:客户向服务器请求服务时,只需传送请求方法和路径。请求方法常用的有GET、HEAD、POST。每种方法规定了客户与服务器联系的类型不同。由于HTTP协议简单,使得HTTP服务器的程序规模小,因而通信速度很快。
3.灵活:HTTP允许传输任意类型的数据对象。正在传输的类型由Content-Type(Content-Type是HTTP包中用来表示内容类型的标识)加以标记。
4.无连接:无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。
5.无状态:HTTP协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快。

我们通过对比可以发现,其实主要的两个不改变的就是无状态,无连接。然后这里的简单快速和灵活的原因就是因为支持客户/服务器模式。也就是媒体独立。总的来说,大概意思是差不多的。

更多HTTP面试资料、笔记添加微信:YDT939获取,还有更多java专题面试资料等你来拿!

TCP协议 (传输控制协议)

上面说http的时候一直有提到tcp协议。这里专门讲一下什么是tcp协议:

传输控制协议(TCP,Transmission Control Protocol)是为了在不可靠的互联网络上提供可靠的端到端字节流而专门设计的一个传输协议。

这个是百度百科的介绍。其实很好理解。为了端到端的数据传输而专门设计的。
用一个我个人的想象的理解:旅行箱/书包/塑料袋是为了我们在一个地方到另一个地方的携带/运输而设计的。如果我从超市买一大堆东西,没有任何包装工具(袋子,箱子,盒子啥的),一起在怀里捧着,可能到家会发现半路上丢了东西。本来想吃火锅,啥都买好了捧到家发现火锅料丢了。完了,整个计划都不能实现了。
同样的道理,两个端数据传输,我们起码得保证传送的和接受的要一样吧?不然一会儿丢个字节,一会儿丢个段落,最后传过去的东西接收方都看不明白,那还有什么意义了?由此,tcp就是这么一个保证文件传输过程中不会丢减字节的协议。
接下来我直接贴上百度百科对tcp的介绍,有空的同学可以看一下,不太复杂。

TCP是一种面向广域网的通信协议,目的是在跨越多个网络通信时,为两个通信端点之间提供一条具有下列特点的通信方式: [1]
(1)基于流的方式;
(2)面向连接;
(3)可靠通信方式;
(4)在网络状况不佳的时候尽量降低系统由于重传带来的带宽开销;
(5)通信连接维护是面向通信的两个端点的,而不考虑中间网段和节点。
为满足TCP协议的这些特点,TCP协议做了如下的规定: [10]
①数据分片:在发送端对用户数据进行分片,在接收端进行重组,由TCP确定分片的大小并控制分片和重组;
②到达确认:接收端接收到分片数据时,根据分片数据序号向发送端发送一个确认;
③超时重发:发送方在发送分片时启动超时定时器,如果在定时器超时之后没有收到相应的确认,重发分片;
④滑动窗口:TCP连接每一方的接收缓冲空间大小都固定,接收端只允许另一端发送接收端缓冲区所能接纳的数据,TCP在滑动窗口的基础上提供流量控制,防止较快主机致使较慢主机的缓冲区溢出;
⑤失序处理:作为IP数据报来传输的TCP分片到达时可能会失序,TCP将对收到的数据进行重新排序,将收到的数据以正确的顺序交给应用层;
⑥重复处理:作为IP数据报来传输的TCP分片会发生重复,TCP的接收端必须丢弃重复的数据;
⑦数据校验:TCP将保持它首部和数据的检验和,这是一个端到端的检验和,目的是检测数据在传输过程中的任何变化。如果收到分片的检验和有差错,TCP将丢弃这个分片,并不确认收到此报文段导致对端超时并重发。

上面的通信方式让我们对tcp有一个更清晰的认识。
下面的规定都是为了保证传递过程中数据不会变。保证发送的和接受的是一样一样的东西。(就好像塑料袋的作用是装进袋子里的东西和到家以后从袋子里拿出来的东西是一样的。别跟我说什么袋子坏掉了,路上偷吃了什么的情况啊!!!)然后我觉得概念还好理解。而且做法也通俗易懂的。一会儿下面还会有提到。

IP

IP地址是IP协议提供的一种统一的地址格式,它为互联网上的每一个网络和每一台主机分配一个逻辑地址,以此来屏蔽物理地址的差异。
其实觉得没啥必要单独讲这个,但是写到这里了,为了统一格式就这样吧,所以ip也单独列出来了。

TCP/IP协议

刚刚关于tcp和IP都单独讲了。现在我们就说说这一组协议。

TCP/IP协议(传输控制协议/互联网协议)不是简单的一个协议,而是一组特别的协议,包括:TCP,IP,UDP,ARP等,这些被称为子协议。在这些协议中,最重要、最著名的就是TCP和IP。因此,大部分网络管理员称整个协议族为“TCP/IP”。
————来源百度百科

就是tcp知识一个传输的协议。我们平时两台电脑上的互相发送信息,是ip协议确定哪两台电脑,然后tcp协议来确确实实是传输数据。

TCP的三次握手

额,这个问题我在好几天的的面经里就提过了,不过今天既然总结到这里了就当复习,重新说一下。
首先明确一点:每次通信都是客户端主动连接服务端的。我们做项目的应该能理解这个。Java之所以是后端开发,人家写页面的之所以是前端开发(我没任何鄙视的意思,就是一个形象的比喻),就是因为每次都是前端调用后端的接口,你做过后端主动去调用前端的啥啥啥?同样这个道理,服务器就跟个饭店似的,一直在那开着,客户端相当于客人,想去吃饭可以进去,然后点菜。但是不能饭店自己主动做个菜强迫某人买吧?
我先言语上大概叙述一下tcp通信的过程,然后有必要直接贴个图上来。
我刚刚寻思怎么解释这个三次握手寻思的我自己都乐的不行。其实如果你想象力和我一样丰富的话,会觉得知识里真的好多乐趣。
我大概说一下,tcp建立一个连接需要三次握手,而终止一个连接要经过四次挥手,这是由TCP的半关闭(half-close)造成的。

建立连接:

  1. 客户端发送SYN(SEQ=x)报文给服务器端,进入SYN_SEND状态。
    (我们可以想象成客户端给服务端发个消息:大哥,聊聊?
    这里的SYN,和SYN_SEND状态,Established状态,有兴趣的自己去找找。个人感觉就像数据库常量定义似的,没啥绝对的意义。)

  2. 服务器端收到SYN报文,回应一个SYN (SEQ=y)ACK(ACK=x+1)报文,进入SYN_RECV状态。
    (服务端收到客户端消息了,寻思反正也没啥事,聊聊就聊聊吧。然后说:行,我是XX,你要是没找错人,聊一会儿也行!)

  3. 客户端收到服务器端的SYN报文,回应一个ACK(ACK=y+1)报文,进入Established状态
    (客户端收到服务端回复说能聊,回了个字:没找错人,就是你。然后这个时候俩人,不对,两台电脑就可以开始传数据了。)

其实咋说呢,我们说的三次握手就是三次数据的传输(个人理解,我不知道准不准确)。就跟你微信跟人聊天似的,
你跟人先说话,给人家发一条:在么?方便么?我发语音了啊?(直男第一问候语)。
人家回你:在,有空,发吧。
你还欠儿欠儿的回了句:那我发了啊!
然后才开始弹语音。
你看看,这是不是也是三条数据?tcp的三次握手我个人感觉就是这样。

三次握手图解

更多HTTP面试资料、笔记添加微信:YDT939获取,还有更多java专题面试资料等你来拿!

结束连接:

  1. 某个应用进程首先调用close,称该端执行“主动关闭”(active close)。该端的TCP于是发送一个FIN分节,表示数据发送完毕。
    (继续上文,那个片发出去了,然后你的电脑上显示发送完毕了。然后你打字说:发完了。)

  2. 接收到这个FIN的对端执行 “被动关闭”(passive close),这个FIN由TCP确认。
    (接收方也直接下载下来了。回了句:嗯,我也下载完了。)

  3. 一段时间后,接收到这个文件结束符的应用进程将调用close关闭它的套接字。这导致它的TCP也发送一个FIN。
    (接收方紧接着又发了一条消息:谢了啊兄弟,我看电影去了啊,拜拜)

  4. 接收这个最终FIN的原发送端TCP(即执行主动关闭的那一端)确认这个FIN。
    (你这个发片的看到以后回复:行,兄弟你忙去吧,注意身体啊,拜拜)

到了这里,你们肮脏的py交易就结束了。连接也结束了。再想联系又要创建一个新的连接了。然后我上一下正经的结束连接的图吧。我也不知道我讲明白没有,反正笑得挺欢。脑补是个好东西啊。

tcp连接的终止

然后TCP的三次握手,和工作过程我感觉也就这样了。好多细节之类的想知道自己去查一些权威资料吧。

HTTP工作过程

最后说一下HTTP的工作流程。
假如你仔细看了上面的内容,应该可以直接理解这个图了。HTTP是一个简单的请求-响应协议,它通常运行在TCP之上。它指定了客户端可能发送给服务器什么样的消息以及得到什么样的响应。然后下图是一次完整的数据传送过程。我真的写不来各种绘图,所以一般复杂一点,段落说不清的我直接手绘传图了。我尽量写的字标准一点,起码能认出来。

http工作过程

然后这篇文章就这样了。有不同意见或者我哪里理解错了说的有问题的欢迎指出,评论或者私聊都可以。共同交流进步嘛!再重申一点!!!我这些也都是看视频,看百度百科,查资料啥的,还要加上自己的一些理解,最后写出来的。可能有的地方没说的很透或者说的很浅薄,欢迎指错。

HTTP超全思维导图: