websocket和Koa2及科普一次完整的HTTP请求过程

第一部分:前端如何实现即时通讯?websocket

基于Web的前端,存在以下几种可实现即时通讯的方式:

  • 短轮询 (开个定时器,每隔一段时间发送请求:实时性不强)

  • Comet-ajax (发送一个请求,服务器只要数据不更新,就一直阻塞:服务器压力过大)

  • SSE(利用了http协议,流数据的传输,并不是养个意义上的双向通讯,无法复用连接)

  • WebSocket(性能和效率都高)

短轮询

短轮询就是客户端定时发送请求,获取服务器上的最新数据。不是真正的即时通讯,但一定程度上可以模拟即时通讯的效果。

优缺点:

  • 优点:浏览器兼容性好,实现简单

  • 缺点:实时性不高,资源消耗高,存在较多无用请求,影响性能

WebSocket

需要下载三方包

npm i ws

服务器端部分

// 以下为webSocket
const http = require('http')
const server = http.createServer();
const WebSocket = require('ws')
const wss = new WebSocket.Server({server})
server.listen(9998)
// 对客户端的连接事件进行监听
// client:代表的是客户端的连接socket对象
wss.on('connection',client=>{
    console.log('有客户端连接成功了。。。')
    // 对客户端的连接对象进行message事件监听
    // msg:由客户端发给服务端的数据
    client.on('message',msg=>{
        console.log('客户端发送数据给服务端了:'+msg)
        // msg为16进制,使用msg.toString()转为字符串
        // 由服务端往客户端发送数据
        client.send(msg.toString()) //必须要传入字符串
    })
})

 浏览器端部分

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    输入内容:<input type="text"><hr/>
    <button id="box1">给服务器发送内容</button>
</body>
<script>
    const ws = new WebSocket('ws://localhost:9998')
    // 连接成功事件
    ws.onopen=()=>{
        console.log('连接服务器成功了。。。')
    }
    ws.onclose=()=>{
        console.log('连接服务器失败了')
    }
    ws.onmessage=(msg)=>{
        console.log(msg)
        console.log(Object.prototype.toString.call(msg.data))
        console.log('接收到从服务器发送过来的数据了',msg.data)
    }

    document.querySelector('#box1').addEventListener('click',()=>{
        // 给服务器发送数据ws.send()
        ws.send(document.querySelector('input').value)
    })
</script>
</html>

第二部分:一次完整的HTTP请求过程

// 1.输入www.baidu.com 回车后,需要先进行DNS解析,得到公网ip
// 2.根据ip地址找到服务器,开始建立TCP连接,三次握手
// 3.浏览器端发送请求,服务器端进行响应 index.html
// 4.浏览器解析 index.html,加载index.html 中需要加载的其他一些资源(css,js,图片)
// 5.浏览器完成页面的解析渲染
// 6.http服务完成,释放关闭TCP连接,四次挥手

第二部分之三次握手

这和礼貌的好友道别一样:(a:客户端,b:服务器)

1、一开始A想要回家离开,但是呢?怕b还有事情要交代,那么呢?只好先向b打招呼,我要走了,请求停止交谈(此时,a到b的链接没有断开,依旧可以进行通信)

2、同意a的请求,说好的,但是我这里可能还有一些话(数据)没说完。我检查看看,你等等,等我说完你再走。

3、b确实没啥要补充的了,就告诉我可以散伙了

4、a说好的,知道了,88,(b得知a走开了,关闭了自己的链接)

 第四部分之四次挥手

(1)一方a发起断开连接的消息

(2)另一方b会确认收到断开的需求,但是会要求等一等,确定是否数据传输完毕(3)b

(3)b当确认完之后,确实数据都传完了,告知a,连接可以断开了

(4)a确认完之后,确实数据都传完了,告知a,连接可以断开

 第三部分:Koa2

Koa2特点

支持async、await

洋葱模型中间件

Koa2快熟上手

第一步:检查Node的环境

node-v

第二步:安装Koa

npm init -y

npm install koa

第三步:创建并编写app.js文件

1.创建Koa对象

2.编写响应中间件

3.监听端口

第四步:启动服务器

node app.js

具体实施过程如下

在app.js中

// 1.创建Koa对象
const Koa = require('koa')
const app = new Koa()
// 绑定第一层中间件
const respDurationMiddleware = require('./middleware/koa_response_duration')
app.use(respDurationMiddleware)
// // 第二层中间件
const respHeaderMiddleware =require('./middleware/koa_response_header')
app.use(respHeaderMiddleware)
// // 第三层中间件
const respDadaMiddleware = require('./middleware/koa_response_data')
app.use(respDadaMiddleware)
// 3.绑定端口号
app.listen(3000,'192.168.87.206',()=>{
    console.log('启动了服务器')
})

 在第二层中间件的文件夹中设置

const respHeaderMiddleware =require('./middleware/koa_response_header')
// 设置响应头的中间件
module.exports=async(ctx,next)=>{
    const contentType ="application/json;charset=utf-8"
    ctx.set('content-type',contentType)
    // 如下为响应头跨域
    ctx.set('Access-Control-Allow-Methods','OPTIONS,GET,PUT,POST,DELETE')
    ctx.set('Access-Control-Allow-Origin',"*")
    // 响应体
    // ctx.response.body="{'success':true}"
    await next()
}

在第一层的中间件中设置

const respDurationMiddleware = require('./middleware/koa_response_duration')
// 计算服务器消耗时长的中间件
module.exports= async(ctx,next)=>{
    // 记录开始时间
    const start = Date.now()
    // 让内层中间件得到执行
    await next()
    // 记录结束时间
    const end = Date.now()
    // 设置响应头X-Response-Time
    const duration = end-start
    // ctx.set设置响应头
    ctx.set('X-Response-Time',duration+'ms')
}

在第三层的中间件中设置

const respDadaMiddleware = require('./middleware/koa_response_data')
// 处理业务逻辑的中间件,读取某一个json文件响应给服务器
// 1.获取请求的路径,拼接文件路径
// 2.读取该路径对应文件的内容
const fs = require("fs")
const path=require('path') 
module.exports= async(ctx,next)=>{
    console.log('第三层中间件')
    // 根据url
    const url = ctx.request.url
    // 获取绝对路径
    let filePath = url.replace('/api','')
    filePath ='/data'+filePath+'.json'
    // 生成绝对路径
    try {
        const conmon = fs.readFileSync(path.join(__dirname,'..',filePath),'utf-8')
        ctx.response.body=conmon.toString()
    } catch (error) {
        const errorMsg={
            "message":"读取文件内容失败,文件资源不存在",
            "status":"404",
        }
        ctx.response.body=JSON.stringify(errorMsg)

    }
    await next()
}

猜你喜欢

转载自blog.csdn.net/m0_62823653/article/details/125919778