• Websocket


    1.什么是Websocket

    WebSocket 是一种在单个TCP连接上进行全双工通信的协议。WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。

    • Tcp,英文全称为Transmission Control Protocol,是一种面向连接的、可靠的、基于字节流的传输层通信协议。通俗一点理解就是在网络世界里的一种信息传递方式,像是现实生活中的写信等等,是电子设备传递信息的一种方式。
    • 全双工,通讯传输的一种方式。除了全双工外,还有半双工和单工。单工指数据只能单向传输,半双工指数据可以双向传输,但是同一时刻只能有一方传输数据,全双工就是指双方可以同时传数据。通俗一点可以理解为单工是单向车道,半双工是潮汐车道,全双工就是双向车道。

    2.Websocket背景

    起初,浏览器是request——response模式,只有当用户向浏览器发送了请求,浏览器才能将数据发送给用户,这种模式下并不支持浏览器主动向用户发送数据,像如今的热门推送,在当时都是无法实现的,当时能做到的最多就是以静态页面的形式推送信息,根本无法和今天的动态获取热门信息相比。为了实现web 页面和服务器之间的实时交互通信,当时的开发人员滥用 XMLHttpRequest 来实现这一功能。最出名的就是长轮询,也就是让 HTTP 连接保持打开状态意味着只要连接保持打开状态,服务器就可以继续持续响应数据,以此来实现服务器与客户端的双向通信。

    长轮询是对原有的询问技术的一种更有效的利用方式,但是向服务器发送重复请求会浪费资源,这需要为每个新传入的请求建立连接,并解析请求的 HTTP 头部,执行对新数据的查询,并且必须生成和交付响应,但是交付的响应往往是没有新数据的。然后又必须关闭连接并清除所有资源。这就对浏览器的性能造成了很大的浪费。直至2008年Websocket被首次提出,时至今日,Websocket已被所有的主流浏览器所支持,前景良好。

    3.Websocket的特点

    1. 建立在 TCP /IP堆栈之上的一个微型传输层,服务器端的实现比较容易。
    2. 与 HTTP 协议有着良好的兼容性。并且握手阶段采用 HTTP 协议,因此握手时不容易屏蔽,能通过各种 HTTP 代理服务器。
    3. 数据格式比较轻量,性能开销小,通信高效。
    4. 可以发送文本,也可以发送二进制数据。
    5. 没有同源限制,客户端可以与任意服务器通信。

    4.简单的websocket尝试

    下面是server.js里的代码,也就是我用node写的简易服务器的代码。由于只是一个练习的小测试,因此并没有什么详细的处理数据的代码,其中的handleOpen(),handleClose(),handleError(),handleConnection(ws)分别是当websocket服务打开,关闭,出错,链接上的时候的相关函数,我只写了打印一句话的代码。handleMessage()是将消息发送给每一个对象的函数

    1. const Ws = require('ws');
    2. ;((Ws) => {
    3. const server = new Ws.Server({ port: 8080 });
    4. const init = () =>{
    5. bindEvent();
    6. }
    7. function bindEvent(){
    8. server.on('open', handleOpen);
    9. server.on('close', handleClose);
    10. server.on('error', handleError);
    11. server.on('connection', handleConnection);
    12. }
    13. function handleOpen(){
    14. console.log("Websocket open");
    15. }
    16. function handleClose(){
    17. console.log("Websocket close");
    18. }
    19. function handleError(){
    20. console.log("Websocket error");
    21. }
    22. function handleConnection(ws){
    23. console.log("Websocket connected");
    24. ws.on('message',handleMessage);
    25. }
    26. function handleMessage(msg){
    27. server.clients.forEach(function(c){
    28. c.send(msg.toString());
    29. })
    30. }
    31. init();
    32. })(Ws);

    下面就是我在js中写的代码了,也就是前端使用websocket服务的时候需要在html使用的js中写的代码。在bindEvent函数中写下监听事件,来实现对应功能的响应。例如当发送按钮按下的时候,执行handleSendBtnClick函数,判断信息是否为空,为空则为误触,否则使用ws.send将信息传递给服务器。handleOpen函数则是用来判断函数名是否存在的,若不存在,则代表没有登录,跳转到登录页面。由于是练习用的,我直接将登录后的用户名存在了本地,在接受信息的时候,也只是简单的根据用户名判断是否为本人,再来使用不同的渲染方式。

    1. ;((doc,WebSocket,storage,location) =>{
    2. const oList = doc.querySelector(".room")
    3. const oMsg = doc.querySelector(".write")
    4. const oSendBtn = doc.querySelector(".send")
    5. const ws = new WebSocket('ws://localhost:8080')
    6. let username = '';
    7. const init = () => {
    8. bindEvent();
    9. }
    10. function bindEvent(){
    11. oSendBtn.addEventListener('click',handleSendBtnClick,false);
    12. ws.addEventListener("open",handleOpen,false);
    13. ws.addEventListener("close",handleClose,false);
    14. ws.addEventListener("error",handleError,false);
    15. ws.addEventListener("message",handleMessage,false);
    16. }
    17. function handleSendBtnClick(){
    18. const msg = oMsg.innerHTML;
    19. if(!msg.trim().length){
    20. return;
    21. }
    22. ws.send(
    23. JSON.stringify({
    24. user:username,
    25. dateTime: new Date().getTime(),
    26. message:msg
    27. })
    28. );
    29. oMsg.innerHTML = ''
    30. }
    31. function handleOpen(e){
    32. console.log("Websocket open",e);
    33. username = Localstorage.getItem("username");
    34. if(!username){
    35. location.href = 'entry.html';
    36. return;
    37. }
    38. }
    39. function handleClose(e){
    40. console.log("Websocket close",e);
    41. }
    42. function handleError(e){
    43. console.log("Websocket error",e);
    44. }
    45. function handleMessage(e){
    46. console.log("Websocket message");
    47. const msgData = typeof e.data =='string' ? JSON.parse(e.data) :e.data;
    48. console.log(msgData)
    49. oList.appendChild(crerateMsg(msgData))
    50. }
    51. function crerateMsg(data){
    52. const { user , dateTime , message } = data;
    53. const oItem = doc.createElement('div');
    54. if(user == storage.getItem("username")){
    55. oItem.innerHTML = `
    56. <div class="mine">
    57. <div class="usermessage">
    58. <img class="headphoto" src="./img/myheader.jpg">
    59. <div class="usernamediv">${ user }</div>
    60. </div>
    61. <div class="messagediv"><span class="message">${ message }</span></div>
    62. </div>
    63. `;
    64. }else{
    65. oItem.innerHTML = `
    66. <div class="others">
    67. <div class="usermessage">
    68. <img class="headphoto" src="./img/headerfive.jpg">
    69. <div class="othernamediv">${ user }</div>
    70. </div>
    71. <div class="messagediv"><span class="othermessage">${ message }</span></div>
    72. </div>
    73. `;
    74. }
    75. return oItem
    76. }
    77. init();
    78. })(document,WebSocket,localStorage,location);

    5.Websocket心跳机制

    由于Websocket下客户端和服务器之间的联系是长时间存在的,有时会就会存在用户长时间未进行操作,也就是客户端和服务器之间长时间不存在通信,此时服务器端是很难判断是用户未进行操作还是连接意外中断,因此就产生了Websocket心跳机制和重连机制。心跳机制是客户端每隔一段时间就会向服务器发送一个数据包,来让服务器得知连接无恙,而服务器在获取到数据包之后,也会给客户端发送一个数据包,让客户端得知连接无恙,倘若出现问题,则代表连接出现问题,进行重连。

  • 相关阅读:
    Web3 治理实践探讨:如何寻找多元化发展路径?
    Js逆向教程-11常见混淆AA和JJ
    转运RNA(tRNA)甲基化修饰7-甲基胞嘧啶(m7C)|tRNA-m7G
    Powershell - 环境设置
    【随笔】Git 高级篇 -- 分离 HEAD(十一)
    java——注释与空行
    Mybatis中SQL注入攻击的3种方式
    怎么添加、修改或删除快递单号
    想要做好代码质量,如何破局?
    Rust根据条件删除相邻元素:dedup
  • 原文地址:https://blog.csdn.net/mhc20201554114/article/details/126712553