javaScript
,HTML
,CSS
.Dom
操做EventLoop
和渲染机制IM
以及超大型高并发网站应用等,例如B站
)在使用某个技术的时候,必定要去追寻原理和底层的实现,久而久之坚持,只要自身底层的基础扎实,不管技术怎么变化,学习起来都不会太累,总的来讲就是拒绝5分钟技术
url
地址,到显示页面发生了什么出发:TCP
连接之上TCP
呢TCP三次握手的过程以下:
SYN
报文给服务器端,进入SYN_SEND
状态。SYN
报文,回应一个SYN
(SEQ=y)ACK(ACK=x+1)报文,进入SYN_RECV状态。如图所示:
TCP
的四次挥手:
注意:FIN的接收也做为一个文件结束符(end-of-file)传递给接收端应用进程,放在已排队等候该应用进程接收的任何其余数据以后,由于,FIN的接收意味着接收端应用进程在相应链接上再无额外数据可接收。css
既然每一个方向都须要一个FIN和一个ACK,所以一般须要4个分节。html
特别提示:SYN
报文用来通知,FIN
报文是用来同步的
以上就是面试官常问的三次握手,四次挥手,可是这不只仅面试题,上面仅仅答到了一点皮毛,学习这些是为了让咱们后续方便了解他的优缺点。
TCP
链接创建后,咱们能够有多种协议的方式通讯交换数据:http 1.0
Http 1.0
的致命缺点,就是没法复用TCP
链接和并行发送请求,这样每次一个请求都须要三次握手,并且其实创建链接和释放链接的这个过程是最耗时的,传输数据相反却不那么耗时。还有本地时间被修改致使响应头expires
的缓存机制失效的问题~(后面会详细讲)
Http 1.1
,这也是技术的发展必然结果~Http 1.1
出现,继承了Http1.0
的优势,也克服了它的缺点,出现了keep-alive
这个头部字段,它表示会在创建TCP
链接后,完成首次的请求,并不会马上断开TCP
链接,而是保持这个链接状态~进而能够复用这个通道Http 1.1
而且支持请求管道化,“并行”发送请求,可是这个并行,也不是真正意义上的并行,而是可让咱们把先进先出队列从客户端(请求队列)迁移到服务端(响应队列)例如:客户端同时发了两个请求分别来获取html和css,假如说服务器的css资源先准备就绪,服务器也会先发送html再发送css。
B站
首页,就有keep-alive
,由于他们也有IM
的成分在里面。须要大量复用TCP
链接~HTTP1.1
好像仍是没法解决队头阻塞的问题实际上,现阶段的浏览器厂商采起了另一种作法,它容许咱们打开多个TCP的会话。也就是说,上图咱们看到的并行,实际上是不一样的TCP链接上的HTTP请求和响应。这也就是咱们所熟悉的浏览器对同域下并行加载6~8个资源的限制。而这,才是真正的并行!
Http 1.1
的致命缺点:
咱们也能够用
dns-prefetch和 preconnect tcp
来优化~
<link rel="preconnect" href="//example.com" crossorigin> <link rel="dns=prefetch" href="//example.com">
Tip
: webpack
能够作任何事情,这些均可以用插件实现Http 2.0
Demo
的性能对比:
Http
的那些致命缺陷,并无彻底解决,因而有了https
,也是目前应用最广的协议之一HTTP+ 加密 + 认证 + 完整性保护 =HTTPS
?由于颇有可能并非和本来预想的通讯方在实际通讯。而且还须要考虑到接收到的报文在通讯途中已经遭到篡改这一可能性。前端
不加密的重要内容被
wireshark
这类工具抓到包,后果很严重~
一般,HTTP 直接和 TCP 通讯。java
加密和解密都会用到密钥。没有密钥就没法对密码解密,反过来讲,任何人只要持有密钥就能解密了。若是密钥被攻击者得到,那加密也就失去了意义。
Https
加密篇幅太长,这篇文章写得很好,你们能够去看看。HTTPS
虽好,非对称加密虽好,可是不要滥用针对速度变慢这一问题,并无根本性的解决方案,咱们会使用 SSL 加速器这种(专用服务器)硬件来改善该问题。该硬件为 SSL 通讯专用硬件,相对软件来说,可以提升数倍 SSL 的计算速度。仅在 SSL 处理时发挥 SSL加速器的功效,以分担负载。react
其中一个缘由是,由于与纯文本通讯相比,加密通讯会消耗更多的 CPU 及内存资源。若是每次通讯都加密,会消耗至关多的资源,平摊到一台计算机上时,可以处理的请求数量一定也会随之减小。webpack
特别是每当那些访问量较多的 Web 网站在进行加密处理时,它们所承担着的负载不容小觑。在进行加密处理时,并不是对全部内容都进行加密处理,而是仅在那些须要信息隐藏时才会加密,以节约资源。git
要进行 HTTPS 通讯,证书是必不可少的。而使用的证书必须向认证机构(CA)购买。证书价格可能会根据不一样的认证机构略有不一样。一般,一年的受权须要数万日元(如今一万日元大约折合 600 人民币)。那些购买证书并不合算的服务以及一些我的网站,可能只会选择采用HTTP 的通讯方式。github
所谓响应头,请求头,其实均可以本身添加字段,只要先后端给对应的处理机制便可
Node.js
代码实现响应头的设置if (config.cache.expires) { res.setHeader("expries", new Date(Date.now() + (config.cache.maxAge * 1000))) } if (config.cache.lastModified) { res.setHeader("last-modified", stat.mtime.toUTCString()) } if (config.cache.etag) { res.setHeader('Etag', etagFn(stat)) } }
Node.js
静态资源服务器,https://github.com/JinJieTan/...,欢迎 star
~websocket
协议开始:
传统的协议没法服务端主动
push
数据,因而有了这些骚操做:
webSocket
.webSockets
的目标是在一个单独的持久链接上提供全双工、双向通讯。在Javascript建立了Web Socket以后,会有一个HTTP请求发送到浏览器以发起链接。在取得服务器响应后,创建的链接会将HTTP升级从HTTP协议交换为WebSocket协议。webSocket
原理: 在TCP
链接第一次握手的时候,升级为ws
协议。后面的数据交互都复用这个TCP
通道。const ws = new WebSocket('ws://localhost:8080'); ws.onopen = function () { ws.send('123') console.log('open') } ws.onmessage = function () { console.log('onmessage') } ws.onerror = function () { console.log('onerror') } ws.onclose = function () { console.log('onclose') }
Node.js
语言实现const express = require('express') const { Server } = require("ws"); const app = express() const wsServer = new Server({ port: 8080 }) wsServer.on('connection', (ws) => { ws.onopen = function () { console.log('open') } ws.onmessage = function (data) { console.log(data) ws.send('234') console.log('onmessage' + data) } ws.onerror = function () { console.log('onerror') } ws.onclose = function () { console.log('onclose') } }); app.listen(8000, (err) => { if (!err) { console.log('监听OK') } else { console.log('监听失败') } })
webSocket
的报文格式有一些不同:![图片上传中...]web
客户端和服务端进行Websocket消息传递是这样的:面试
ping
andpong
Go
实现:package main import ( "net/http" "time" "github.com/gorilla/websocket" ) var ( //完成握手操做 upgrade = websocket.Upgrader{ //容许跨域(通常来说,websocket都是独立部署的) CheckOrigin:func(r *http.Request) bool { return true }, } ) func wsHandler(w http.ResponseWriter, r *http.Request) { var ( conn *websocket.Conn err error data []byte ) //服务端对客户端的http请求(升级为websocket协议)进行应答,应答以后,协议升级为websocket,http创建链接时的tcp三次握手将保持。 if conn, err = upgrade.Upgrade(w, r, nil); err != nil { return } //启动一个协程,每隔5s向客户端发送一次心跳消息 go func() { var ( err error ) for { if err = conn.WriteMessage(websocket.TextMessage, []byte("heartbeat")); err != nil { return } time.Sleep(5 * time.Second) } }() //获得websocket的长连接以后,就能够对客户端传递的数据进行操做了 for { //经过websocket长连接读到的数据能够是text文本数据,也能够是二进制Binary if _, data, err = conn.ReadMessage(); err != nil { goto ERR } if err = conn.WriteMessage(websocket.TextMessage, data); err != nil { goto ERR } } ERR: //出错以后,关闭socket链接 conn.Close() } func main() { http.HandleFunc("/ws", wsHandler) http.ListenAndServe("0.0.0.0:7777", nil) }
Node.js
实现):this.heartTimer = setInterval(() => { if (this.heartbeatLoss < MAXLOSSTIMES) { events.emit('network', 'sendHeart'); this.heartbeatLoss += 1; this.phoneLoss += 1; } else { events.emit('network', 'offline'); this.stop(); } if (this.phoneLoss > MAXLOSSTIMES) { this.PhoneLive = false; events.emit('network', 'phoneDisconnect'); } }, 5000);
new Socket
开始:SDK
接入,可是逼格高些仍是本身重写比较好。IM
桌面应用开发的~const {Socket} = require('net') const tcp = new Socket() tcp.setKeepAlive(true); tcp.setNoDelay(true); //保持底层tcp连接不断,长链接 指定对应域名端口号连接 tcp.connect(80,166.166.0.0) 创建链接后 根据后端传送的数据类型 使用对应不一样的解析 readUInt8 readUInt16LE readUInt32LE readIntLE等处理后获得myBuf const myBuf = buffer.slice(start);//从对应的指针开始的位置截取buffer const header = myBuf.slice(headstart,headend)//截取对应的头部buffer const body = JSON.parse(myBuf.slice(headend-headstart,bodylength).tostring()) //精确截取数据体的buffer,而且转化成js对象
即时通信强烈推荐使用Golang
,GRPC
,Prob
传输数据。
webpack-electron-react-websocket
的Demo, https://github.com/JinJieTan/... 以为写得不错,能够点个赞支持下,文章也借鉴了一下其余大佬的文章,可是地址都贴上来了~ 欢迎gitHub
点个star
哦~