zoukankan      html  css  js  c++  java
  • 三分钟搭建websocket实时在线聊天,项目经理也不敢这么写

    我们先看一下下面这张图:

    在这里插入图片描述

    可以看到这是一个简易的聊天室,两个窗口的消息是实时发送与接收的,这个主要就是用我们今天要讲的websocket实现的。

    websocket是什么?

    websocket是一种网络通信协议,我们都知道http协议,http协议只能从客户端主动发起,不能从服务端推送数据到客户端,今天我们讲的websocket就是一种不仅能从客户端发送数据到服务端,也可以主动从服务的推送数据给客户端的一种协议。
    我们先看一张图:

    在这里插入图片描述

    我们可以看到,http请求是客户端发起请求,服务端响应,然后断开连接,客户端发起,服务端响应的一种循环。而websocket协议是客户端发起连接后,就会一直保持连接,期间客户端和服务端都可以向对方发送数据,直到连接关闭。
    websocket其他的一些特点:

    (1)建立在 TCP 协议之上,服务器端的实现比较容易。

    (2)与 HTTP 协议有着良好的兼容性。默认端口也是80和443,并且握手阶段采用 HTTP 协议,因此握手时不容易屏蔽,能通过各种 HTTP 代理服务器。

    (3)数据格式比较轻量,性能开销小,通信高效。

    (4)可以发送文本,也可以发送二进制数据。

    (5)没有同源限制,客户端可以与任意服务器通信。

    (6)协议标识符是ws(如果加密,则为wss),服务器网址就是 URL。

    应用场景

    试想一下这样的场景,我们需要实现一个支付成功后,向用户给一个成功的提示,那么在websocket协议没有应用之前,人们是使用一种轮询的方式。就是客户端定时向服务端发送请求,看有没有收到支付金额,没有就一直发送,收到了再停止。类似下面的代码:

    function getIsPaySuccess() {
    	var timmer = setInterval(function () {
    		$.ajax({
    			url: '/getJayStatus',
    			success: function (res) {
    				if (res.status) {
    					clearInterval(timmer)
    				}
    			},
    			fail: function () {
    
    			}
    		})
    	}, 1000)
    }
    

    在发送请求的工程中,浪费了大量的资源,而且响应也不是及时的,因为我是每隔1秒请求一次,并不能立刻得到支付成功的状态。这时候我们就需要用到websocket的方式了。总体来说,websocket需要用在一些能及时响应的场景中。

    1. 社交订阅
    有时候我们需要及时收到订阅消息,比如说开奖通知,比如说在线邀请,支付结果等。

    2. 多玩家游戏
    很多游戏都是协同作战的,玩家的操作和状态肯定需要及时同步到所有玩家。

    3. 协同编辑文档
    同一份文档,编辑状态得同步到所有参与的用户界面上。

    4. 数据流状态
    比如说上传下载文件,文件进度,文件是否上传成功。

    5. 多人聊天
    很多场景下都需要多人参与讨论聊天,用户发送的消息得第一时间同步到所有用户。

    6. 股票虚拟货币价格
    股票和虚拟货币的价格都是实时波动的,价格跟用户的操作息息相关,及时推送对用户跟盘有很大的帮助。

    代码实现

    我们用下面一段代码来讲解websocket的创建,拥有的属性,能调用的方法和能监听的事件:

    // 连接状态的枚举
    const readyStateMap = {
    	0: '连接尚未建立',
    	1: '连接已建立,可以进行通信',
    	2: '连接正在进行关闭',
    	3: '连接已经关闭或者连接不能打开'
    }
    Object.freeze(readyStateMap)
    class WsTest {
    	constructor(url) {
    		// 创建websocket实例,第一个参数是连接的url,没有跨域限制,第二个参数是可接受的协议
    		this.ws = new WebSocket(url);
    		// readyState属性,只读属性,表示连接状态
    		console.log(this.ws.readyState, readyStateMap[this.ws.readyState])
    		// 只读属性 bufferedAmount 已被 send() 放入正在队列中等待传输,但是还没有发出的 UTF-8 文本字节数。
    		console.log(this.ws.bufferedAmount)
    		this.initWs()
    	}
    	initWs() {
    		// 事件onopen,指连接成功
    		this.ws.onopen = () => {
    			console.log(this.ws.readyState, readyStateMap[this.ws.readyState])
    			// 方法,向服务端发送消息,传输字符串
    			this.ws.send(JSON.stringify({type: 'connection'}))
    		};
    		// 事件onmessage,指接收到服务端消息
    		this.ws.onmessage = (evt) => {
    			console.log(evt.data, 'data')
    			const {type, msg} = JSON.parse(evt.data);
    			console.log('消息类型:' + type, '用户id:' + msg)
    			// 方法,关闭连接
    			this.ws.close()
    			console.log(this.ws.readyState, readyStateMap[this.ws.readyState])
    		};
    		// 事件onclose,关闭连接,也可以从服务端强制断开连接,这里可以重新发起连接
    		this.ws.onclose = () => {
    			console.log(this.ws.readyState, readyStateMap[this.ws.readyState])
    		};
    		// 事件onerror,通信发生错误时触发
    		this.ws.onerror = () => {
    			console.log(this.ws.readyState, readyStateMap[this.ws.readyState])
    		};
    	}
    }
    const ws = new WsTest('ws://203.195.156.57:30002')
    

    上面的代码都有注释,应该不难看出websocket的使用方法,这段代码可以直接放到chrome控制台运行:

    在这里插入图片描述

    兼容性

    2.png

    可以看到几乎所有浏览器都支持了。

    总结

    1. websocket是一个类似http的一种通讯协议。
    2. websocket最大的特点是客户端和服务端能相互给对方发送消息。
    3. websocket广泛引用在需要实时通讯的一些应用上面。
    4. websocket没有同源限制,而且性能开销小,通信高效。

    本文主要讲了websocket协议的定义和基本用法,下一期我会结合本文开始的聊天室来实现一个具体的websocket应用。

    聊天室在线体验地址:关注公众号:程序零世界 体验在线聊天
    

    学习如逆水行舟,不进则退,前端技术飞速发展,如果每天不坚持学习,就会跟不上,我会陪着大家,每天坚持推送博文,跟大家一同进步,希望大家能关注我,第一时间收到最新文章。

    file

  • 相关阅读:
    设计模式13---设计模式之观察者模式(Observer)(行为型)
    codeforces 166C Median
    HDU 1176 免费馅饼
    老鸟的Python新手教程
    setsockopt()使用方法(參数具体说明)
    RelativeLayout经常使用属性介绍
    java多线程模拟生产者消费者问题,公司面试常常问的题。。。
    JAVA实现HTTPserver端
    进程间通信_03命名管道
    expdp&impdp
  • 原文地址:https://www.cnblogs.com/MonsterJ/p/13055244.html
Copyright © 2011-2022 走看看