当前位置:网站首页>浅谈WebSocket
浅谈WebSocket
2022-07-28 12:49:00 【Maic】
WebSocket是一种基于
http的通信协议,服务端可以主动推送信息给客户端,客户端也可以向服务端发送请求,WebSocket允许服务端与客户端进行全双工通信。
特点
- 基于
tcp协议之上,服务端实现比较容易 - 默认端口是
80(ws)或者443(wss),握手阶段采用的http协议 - 数据格式比较轻量,性能开销小,通信高效
- 可以发送文本或者二进制数据
- 没有同源限制,客户端可以向任意服务器发送信息
- 协议标识符是
ws,如果加密,那么是wss
实现客户端与服务端通信
新建一个html文件客户端代码
<!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>websocket</title>
</head>
<body>
<h3>hello websocket</h3>
<input type="number" id="textContent" />
<button id="handleSend">发送</button>
<button id="auto-send">开启服务端向客户端发消息模式</button>
<hr />
<div id="app"></div>
</body>
</html>
在html中引入下面一段js
// index.js
const sendDom = document.getElementById('send');
const appDom = document.getElementById('app');
const autoDom = document.getElementById('auto-send');
const inputContent = document.getElementById('textContent');
const socketPath = 'ws://192.168.31.40:3000';
let timer = null;
let num = 0;
const result = [];
// 建立连接
const ws = new WebSocket(socketPath);
const sendMyNum = (isSetInterval = false, to = 'client', val) => {
const setNum = () => {
num = val || Math.ceil(Math.random() * 10);
ws.send(
JSON.stringify({
clientText: `client:hello,我是 ${num}号`,
num,
to
})
);
};
if (isSetInterval) {
timer = setInterval(() => {
setNum();
}, 1000);
} else {
setNum();
}
};
const renderHtml = (data) => {
const { serverText, clientText } = JSON.parse(data);
appDom.innerHTML = '';
result.push({
serverText,
clientText
});
console.log(result);
if (result.length > 0) {
let str = '';
result.forEach((v) => {
str += `<ul>
<li>${v.clientText}</li>
<li>${v.serverText}</li>
</ul>`;
});
appDom.innerHTML = str;
}
};
// 发送数据
ws.onopen = function () {
console.log('websocket connection start');
sendMyNum(false);
};
// 接收服务端发送的消息
ws.onmessage = function (evt) {
console.log(`receive:${evt.data}`);
if (evt.data) {
renderHtml(evt.data);
// 接收数据后关闭定时器
clearInterval(timer);
// sendMyNum(true)
}
};
// 关闭连接
ws.onclose = function () {
console.log('关闭了');
};
// 手动向客户端发送消息
handleSend.onclick = function () {
const val = inputContent.value;
if (val === '') {
alert('请输入你的编号');
return;
}
sendMyNum(false, 'client', val);
};
// 自动开启向客户端发送消息
autoDom.onclick = function () {
sendMyNum(true, 'server');
};
新建一个server目录,创建服务端代码,主要依赖`nodejs-websocket`[1]这个库是服务端websocket代码。
var ws = require("nodejs-websocket");
var http = require('http');
const fs = require('fs');
const path = require('path');
const PORT = 8080;
var server = http.createServer(function (request, response) {
response.statusCode = 200;
response.setHeader('Content-Type', 'text/html');
fs.readFile(path.resolve(__dirname, '../', 'index.html'), (err, data) => {
if (err !== null) {
response.end('404');
return;
}
response.end(data);
})
});
server.listen(PORT, function (evt) {
console.log((new Date()) + ' Server is listening on port 8080');
});
// websocket
const tcp = ws.createServer(function (connection) {
console.log("New connection")
connection.on("text", function (data) {
const { clientText, num, to } = JSON.parse(data);
if (to === 'server') {
connection.sendText(JSON.stringify({
serverText: `server:${num}号,恭喜你,你太幸运了,你已经被清华录取了`,
clientText: `${num}号`
}));
} else {
if (num > 6) {
connection.sendText(JSON.stringify({
clientText,
serverText: `server:${num}号,你非常优秀, ${num}号,你已经成功被录取了北京大学`,
}))
} else {
connection.sendText(JSON.stringify({
serverText: `server: ${num}号,非常遗憾,${num}号,你落榜了,再接再厉`,
clientText,
}));
};
}
});
connection.sendText(JSON.stringify({
serverText: `server:hello,我们已经建立连接了`,
clientText: `client:你好`
}))
connection.on("close", function (code, reason) {
console.log("Connection closed");
console.log(code, reason);
});
}).listen(3000);
tcp.on('error', (err) => {
console.log(err);
})
我们可以执行命令node server.js,打开浏览器http://localhost:8080/
打开network,ws下面可以看到有客户端向服务端发送的消息,也有服务端向客户端发送的两条信息。
我们看到请求头的一些信息
我们可以看到请求头里
General
Request URL: ws://192.168.31.40:3000/
Request Method: GET
Status Code: 101 Switching Protocols
Request Headers
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
Cache-Control: no-cache
Connection: Upgrade
Host: 192.168.31.40:3000
Origin: http://localhost:8080
Pragma: no-cache
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits
Sec-WebSocket-Key: Mk8Au85XqQTn+vuDsfr/kw==
Sec-WebSocket-Version: 13
Upgrade: websocket
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36
当输入数字,向服务端发送消息时,服务端会返回对应信息。通常来讲,服务端会不定时的向客户端推送信息,客户端拿到推送信息进行一系列的页面状态展示等。
通过以上的例子,我们基础的了解到websocket的使用
总结
WebSocket其实需要客户端对WebSocket处理主要是这三个步骤
- 建立连接、断开连接
- 发送数据,接收数据
- 处理错误
- 本文 示例代码[2]
更多WebSocket可以参考`websocket`[3]
参考资料
[1]nodejs-websocket: https://www.npmjs.com/package/nodejs-websocket
[2]示例代码: https://github.com/maicFir/lessonNote/tree/master/node/websocket
[3]websocket: https://www.wangdoc.com/webapi/websocket.html
边栏推荐
- How to play a data mining game entry Edition
- .NET桌面开发的一些思考
- Excellent performance! Oxford, Shanghai, AI Lab, Hong Kong University, Shangtang, and Tsinghua have joined forces to propose a language aware visual transformer for reference image segmentation! Open
- [ecmascript6] function and its related use
- R language test sample proportion: use prop The test function performs the single sample proportion test to calculate the confidence interval of the p value of the successful sample proportion in the
- SAP UI5 FileUploader 控件实现本地文件上传,接收服务器端的响应时遇到跨域访问错误的试读版
- 最强分布式锁工具:Redisson
- 比XShell更好用、更现代的终端工具!
- DOJNOIP201708奶酪题解
- C语言:顺序存储结构的快速排序
猜你喜欢

Socket类关于TCP字符流编程的理解学习

111. SAP UI5 FileUploader 控件实现本地文件上传,接收服务器端的响应时遇到跨域访问错误

Product Manager: job responsibility table

Jar package

半波整流点亮LED

Cool operation preheating! Code to achieve small planet effect

Three men "running away" from high positions in the mobile phone factory

SQL daily practice (Niuke new question bank) - day 4: advanced operators

GO语言-栈的应用-表达式求值

面经整理,助力秋招,祝你称为offer收割机
随机推荐
To build agile teams, these methods are indispensable
30天刷题计划(三)
《如何打一场数据挖掘赛事》入门版
How to check if the interface cannot be adjusted? I didn't expect that the old bird of the 10-year test was planted on this interview question
GO语言-栈的应用-表达式求值
111. SAP UI5 FileUploader 控件实现本地文件上传,接收服务器端的响应时遇到跨域访问错误
30 day question brushing plan (IV)
R语言使用dpois函数生成泊松分布密度数据、使用plot函数可视化泊松分布密度数据(Poisson distribution)
Is azvudine, a domestic oral new coronal drug, safe? Expert authority interpretation
数据库系统原理与应用教程(062)—— MySQL 练习题:操作题 32-38(六)
剖析 kubernetes 集群内部 DNS 解析原理
R language Visual scatter diagram, geom using ggrep package_ text_ The repl function avoids overlapping labels between data points (add labels to specific areas of the visual image using the parameter
【C语言】结构体指针与结构体变量作形参的区别
7.依赖注入
Tutorial on the principle and application of database system (059) -- MySQL exercise questions: operation questions 1-10 (III)
拒绝服务 DDoS 攻击
After finishing, help autumn move, I wish you call it an offer harvester
The strongest distributed locking tool: redisson
Rolling update strategy of deployment.
使用 Fail2ban 保护 Web 服务器免受 DDoS 攻击