前言:http协议经常作为面试的考点,自己之前对其还不是很了解,直到面试时被问到一个关于http协议的问题,才恍然大悟。下面分享一下。
文章目录
一. http协议入门
1.1 简介
http协议是从服务器传输超文本到本地浏览器的传送协议,是基于 TCP/IP 协议来传递数据(HTML 文件、图片文件、查询结果等) ,默认使用80端口。
1.2 http报文
Http报文包括请求报文和响应报文两大部分,其中请求报文由请求行(request line)、请求头(header)、空行和请求体四个部分组成。而响应报文由状态行、响应头部、空行和响应体四个部分组成。
1.2.1 请求报文
-
请求行
用来说明请求类型、要访问的资源、以及所使用的HTTP版本。如:
POST /1.jpg HTTP/1.1
-
请求头
由 key/value 对组成,每行一对,关键字和值之间冒号":"分割。常见的有:
- Host:主机和端口号
- Connection:表示是否需要持久连接(HTTP 1.1默认进行持久连接),持久连接的优点就是当页面包含多个元素时显著地减少下载所需要的时间。
- Content-Length:表示请求消息正文的长度
- Cookie:这是最重要的请求头信息之一
- Referer:包含一个URL,用户从该URL代表的页面出发访问当前请求的页面(一个网站统计流量来源就是用的这个)
- Accept:浏览器可接受的MIME类型
- Accept-Charset:浏览器可接受的字符集
- Accept-Encoding:浏览器能够进行解码的数据编码方式,比如gzip。Servlet能够向支持gzip的浏览器返回经gzip编码的HTML页面。许多情形下这可以减少5到10倍的下载时间
- Accept-Language:浏览器所希望的语言种类,当服务器能够提供一种以上的语言版本时要用到
-
空行
最后一个请求头之后是一个空行,它表示请求头已经结束,接下来的是请求正文。
-
请求体
可以承载多个请求参数的数据。一般用json数据。
1.2.2 响应报文
-
响应行
一般由协议版本、状态码及其描述组成。如:
HTTP/1.1 200 OK
常见状态码:
- 100~199:表示成功接收请求,要求客户端继续提交下一次请求才能完成整个处理过程。
- 200~299:表示成功接收请求并已完成整个处理过程。常用200
- 300~399:为完成请求,客户需进一步细化请求。例如:请求的资源已经移动一个新地址、常用302(意味着你请求我,我让你去找别人),304和307(我不给你这个资源,自己拿缓存)
- 400~499:客户端的请求有错误,常用404(意味着你请求的资源在web服务器中没有),403(服务器拒绝访问,权限不够)
- 500~599:服务器端出现错误,常用500
-
响应头
响应头用于描述服务器的基本信息,以及数据的描述,服务器通过这些数据的描述信息,可以通知客户端如何处理等一会儿它回送的数据。常见的有:
- Content-Encoding:文档的编码(Encode)方法。只有在解码之后才可以得到Content-Type头指定的内容类型。利用gzip压缩文档能够显著地减少HTML文档的下载时间。
- Content-Length:表示内容长度。只有当浏览器使用持久HTTP连接时才需要这个数据。如果你想要利用持久连接的优势,可以把输出文档写入 ByteArrayOutputStram,完成后查看其大小,然后把该值放入Content-Length头,最后通过byteArrayStream.writeTo(response.getOutputStream())发送内容。
- Content-Type:表示后面的文档属于什么MIME类型。Servlet默认为text/plain,但通常需要显式地指定为text/html。由于经常要设置 Content-Type,因此HttpServletResponse提供了一个专用的方法setContentType方法。(重要,后面的编码需要用这个)
- Location:这个头配合302状态码使用,用于重定向接收者到一个新URI地址。表示客户应当到哪里去提取文档。Location通常不是直接设置的,而是通过HttpServletResponse的sendRedirect方法,该方法同时设置状态代码为302。
-
空行
最后一个响应头之后是一个空行,它表示请求头已经结束,接下来的是请求正文。
-
响应体
响应体就是响应的消息体,如果是纯数据就是返回纯数据,如果请求的是HTML页面,那么返回的就是HTML代码。
1.3 持久连接
HTTP协议的初始版本中,每进行一次HTTP通信就要断开一次TCP连接。以当年的通信情况来说,因为都是些容量很小的文本传输,所以即使这样也没有多大问题。可随着 HTTP 的普及,文档中包含大量图片的情况多了起来。比如,使用浏览器浏览一个包含多张图片的 HTML 页面时,在发送请求访问 HTML 页面资源的同时,也会请求该 HTML 页面里包含的其他资源。因此,每次的请求都会造成无谓的 TCP 连接建立和断开,增加通信量的开销。为解决这个问题,在 HTTP/1.1
中,所有的连接默认都是持久连接,只要任意一端没有明确提出断开连接,则保持TCP连接状态。减轻了服务器的负载,所以web页面显示速度就提高了。
1.4 get请求和post请求的区别
- GET在浏览器回退时是无影响的,而POST会再次提交请求。
- GET请求会被浏览器主动缓存,而POST不会。
- GET 请求保留在浏览器历史记录中, POST 请求不会保留在浏览器历史记录中。
- GET请求在URL中传送的参数是有长度限制的(在url中),而POST没有限制(在请求体中)。
- GET产生一个TCP数据包;POST产生两个TCP数据包。对于GET方式的请求,浏览器会把http header和data一并发送出去,服务器响应200(返回数据);而对于POST,浏览器先发送header,服务器响应100 continue,浏览器再发送data,服务器响应200 ok(返回数据)。
二.用socket实现http协议
目标:java代码运行起来后,在页面上输入localhost:8080/1.jpg,显示一张图片出来。
分析:这个肯定是需要自己创建一个本地服务器,接收客户端的http请求,并作出响应。那么就肯定是需要用socket来实现http协议了吧,下面附上代码。有许多多余的代码,方便大家了解http报文,可以略,有效代码比较少,熟悉http协议的话,很容易就能写出来。
package cn.server;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java