内容简介:http那些事
简介
超文本传输协议,这决定了协议传输的内容。
如果你想了解一个http协议,就用一门语言基于socket包写一个特定的响应,然后基于浏览器访问它。
http1.1
基于node.js socket写一个简单的http server
require('net').createServer(function(sock) { sock.on('data', function(data) { sock.write('HTTP/1.1 200 OK\r\n'); sock.write('\r\n'); sock.write('hello world!'); sock.destroy(); }); }).listen(9090, '127.0.0.1');
scala版本
object SocketServer { def main(args: Array[String]): Unit = { try { val listener = new ServerSocket(8080); val socket = listener.accept() val data = "HTTP/1.1 200 OK\r\nContent-Length: 12\r\n\r\nhello world!" socket.getOutputStream.write(data.getBytes()) socket.close() listener.close() } catch { case e: IOException => System.err.println("Could not listen on port: 80."); System.exit(-1) } } }
long polling
http long-polling(推送),服务端故意不响应(一段时间),也不断连接。参见 面试时如何优雅的谈论HTTP/1.0/1.1/2.0
Content-Encoding
http协议中有 Content-Encoding(内容编码)。Content-Encoding 通常用于对实体内容进行压缩编码,目的是优化传输,例如用 gzip 压缩文本文件,能大幅减小体积。内容编码通常是选择性的,例如 jpg / png 这类文件一般不开启,因为图片格式已经是高度压缩过的。
内容编码针对的只是传输正文。在 HTTP/1 中,头部始终是以 ASCII 文本传输,没有经过任何压缩,这个问题在 HTTP/2 中得以解决。
Transfer-Encoding
参见 HTTP 协议中的 Transfer-Encoding
Transfer-Encoding 用来改变报文格式。这涉及到一个通信协议的重要问题:如何定义协议数据的边界
- 发送完就断连接(非持久连接)
- 协议头部设定content-length
- 以特殊字符结尾
content-length有几个问题:
- 发送数据时,对某些场景,计算数据长度本身是一个比较耗时的事情,同时会占用一定的memory。
- 接收数据时,从协议头拿到数据长度,接收不够这个长度的数据,就不能解码后交给上层处理。
Transfer-Encoding 当下只有一个可选值:分块编码(chunked)。这时,报文中的实体需要改为用一系列分块来传输。每个分块包含十六进制的长度值和数据,长度值独占一行,长度不包括它结尾的 CRLF(\r\n),也不包括分块数据结尾的 CRLF。最后一个分块长度值必须为 0,对应的分块数据没有内容,表示实体结束。
require('net').createServer(function(sock) { sock.on('data', function(data) { sock.write('HTTP/1.1 200 OK\r\n'); sock.write('Transfer-Encoding: chunked\r\n'); sock.write('\r\n'); sock.write('b\r\n'); sock.write('01234567890\r\n'); sock.write('5\r\n'); sock.write('12345\r\n'); sock.write('0\r\n'); sock.write('\r\n'); }); }).listen(9090, '127.0.0.1');
server push
服务器可以对一个客户端请求发送多个响应。服务器向客户端推送资源无需客户端明确地请求。
http2
复用
复用是http2许多特性的起点,因为一个域名只可以使用一个连接,所以在连接之上提出stream的概念,一个stream一般代表一个业务。一个stream可以收发多次请求响应,每次是一个消息(消息的定义是语义上的),一个消息包括多个帧(比如header frame和data frame)。
反过来说, http作为双工通信,必须是一个“相互对应的”request和response才完整。
- http1.0 一个请求一个新连接,我发出的是reqeust,我收到的是response,连接关闭,response接收完毕,对应关系自然建立。但因为发送的时候不能接受数据,(服务端未收到请求,自然不知道如何响应),基本是单工通信。
- http1.1 多个请求复用连接,但要求server必须按照request的顺序返回response,对应关系也可以建立起来。
很明显,理想状态应该是
- client 按需发request,server按处理能力返回response,通过额外的手段将两者关联起来(一般通过一个id)
- 不必非得整收整发。此处与上文的分块传输类似,http2做的更加彻底,一个是分块可以是二进制。再则,http1.1分块只是解决了边界问题,http2则应该是在分块(frame)的粒度进行数据编解码。
至于http2的代码展示,因为在浏览器执行url前,还有一次协议协商过程(浏览器最初以http1.1协议发起请求,和server协商一致后转用http2),不好模拟,所以作罢。参见 HTTP/2协议–特性扫盲篇
https
来自《http权威指南》
对web服务器发起请求时,我们需要一种方式来告知web服务器去执行http的安全协议版本,这是通过url中设定http或https来实现的。
- 如果是http,客户端就会打开一条到服务器80端口的连接
- 如果是https,客户端就会打开一条到服务器443端口的连接,一旦建立连接,client和server就会初始化ssl layer,对加密参数进行沟通,并交换密钥。ssl握手完成之后, ssl layer初始化完成了。 剩下的就是,browser将数据从http layer发到tcp layer之前,要经过ssl layer加密。
以上所述就是小编给大家介绍的《http那些事》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。