webSocket

介绍:

readyState表示连接有四种状态:

  1. connecting (0):表示还没建立连接;

  2. open    (1): 已经建立连接,可以进行通讯;

  3. closing (2):通过关闭握手,正在关闭连接;

  4. closed  (3):连接已经关闭或无法打开; 

前端代码表示

原生JS(HTML+JS)

HTML文件

<!DOCTYPE HTML>
<html>

<head>
    <meta charset="utf-8">
    <title>通信</title>
</head>

<body>
<ul id="list"></ul>
<input  type="text" id="message" placeholder="请输入内容"  />
<button id="send">发送</button>


  <script src="XXX.js> </script>
   
   
</body>
</html>

JS文件


//立即执行函数,避免全局变量之间的污染
;((doc)=>{

const oList=doc.querySelector('#list');
const oMsg=doc.querySelector('#message');
const oSendBtn.querySelector('#send');
const ws=new Socket('ws:localhost:8000');//创建一个Socket实例

//初始化函数
const init=()=>{
bindEvent();
}

//绑定事件函数,监听oSendBtn,
//最后参数是指定事件是否在捕获或冒泡阶段执行,false是默认冒泡阶段执行,true捕获阶段执行
function bindEvent(){
  oSendBtn.addEventListener('click',handSendBtnClick,false);  
  ws.addEventListener('open',handOpen,false);
  ws.addEventListener('close',handClose,false);
  ws.addEventListener('error',handError,false);
  ws.addEventListener('message',handMessage,false);
}

//具体的点击事件
function handSendBtnClick(){
console.log('发送的具体消息')
  const msg=oMsg.value
   if(!msg.trim().length){
     return
   }
//发送的应该为字符串
  ws.send(JSON.stringfy({ 
     dataTime:new Data().getTime(),
     message:msg 
}))  

oMsg.value=''
}

//socket的四个事件
function handOpen(){
console.log('打开')
}

function handClose(){
console.log('关闭')
}

function handError(){
console.log('')
}

function handMessage(e){
console.log('接收消息',e.data)
const msgData=JSON.parse(e.data) //转化为对象
oList.appendChild(createMsg(msgData)) //转为li
}
//做成LI的格式
function createMsg(data){
const {user,dataTime,message}=data
const oItem=doc.createElement('li')
oItem.innerHTML=`
<p>
<span>${user}</span>
<li>${new Data()}</li>
</p>
<p>消息:${message}</p>
`
return oItem
}


init()


})(document);

​​​​​​​纯HTML

<!DOCTYPE HTML>
<html>

<head>
    <meta charset="utf-8">
    <title>聊天室</title>

    <script type="text/javascript">

        var ws = null;
        var interval = null;
        var uri = "ws://192.168.110.92:8080/schedule/websocket/connect";
        var myVar = null;
        var reconnectState = null;

        function WebSocketTest() {
            if ("WebSocket" in window) {
                createWebSocket();
            } else {
                // 浏览器不支持 WebSocket
                alert("您的浏览器不支持 WebSocket!");
            }
        }

        /**
       * 创建websocket
       */
        function createWebSocket() {
            alert("开启长连接")
            // 打开一个 web socket
            ws = new WebSocket(uri);
            ws.onopen = function () {
                document.getElementById("reconnectShow").innerText = "无";
                document.getElementById("online").innerText = "在线";
                reconnectState = false;
                clearInterval(myVar);
                // 心跳检测
                interval = setInterval(function () {
                    // 使用 send() 方法发送数据		
                    sendMsg("ping");
                }, 5000);

            };

            ws.onmessage = function (evt) {
                var received_msg = evt.data;
                console.log("回复",evt.data);
                if (received_msg == "pong") {
                    console.log(received_msg);
                } else {
                    document.getElementById("num").innerText = received_msg;
                }
            };

            ws.onclose = function () {
                webscoketClose();
            };
        }


        /**
       * websocket重连
       */
        function reconnect() {
            // 检测到websocket连接断开
            // 0 (WebSocket.CONNECTING)正在链接中
            // 1 (WebSocket.OPEN)已经链接并且可以通讯
            // 2 (WebSocket.CLOSING) 连接正在关闭
            // 3 (WebSocket.CLOSED)连接已关闭或者没有链接成功
            if (reconnectState == false) {
                reconnectState = true;
                var reconnectNum = 1;
                console.log(ws.readyState);
                myVar = setInterval(function () {
                    if (ws.readyState == 2 || ws.readyState == 3) {
                        if (reconnectNum == 6) {
                            clearInterval(myVar);
                            document.getElementById("reconnectShow").innerText = "停止重连";
                            return;
                        }
                        document.getElementById("reconnectShow").innerText = "第" + reconnectNum + "次尝试重连中";
                        createWebSocket();
                        reconnectNum++;
                    }

                }, 5 * 1000)
            }
        }

        function noReconnectclose() {
            reconnectState = true;
            webscoketClose();
        }

        /**
         * websocket关闭 
         */
        function webscoketClose() {
            ws.close();
            clearInterval(interval)
            console.log("websocket关闭");
            document.getElementById("online").innerText = "离线";
            // 开启断线重连
            reconnect();
        }

        function sendMsg(str) {
            if (ws.readyState == 1) {
                ws.send(str);
                // alert("发送内容");
            } else {
                alert("未连接上服务器");
            }
        }

        function add() {
            sendMsg("+1");
        }

        function remove() {
            sendMsg("-1");
        }

    </script>

</head>

<body>
    <div id="sse">
        <a href="javascript:WebSocketTest()">运行 WebSocket</a>
        <a href="javascript:noReconnectclose()">停止 WebSocket</a>
    </div>
    <br>
    当前webscoket状态:<span id="online">离线</span>
    <br>
    当前重连状态:<span id="reconnectShow">无</span>
    <br>
    当前怒气值:<span id="num">0</span>
    <br>
    <a href="javascript:add()">+1</a>
    <a href="javascript:remove()">-1</a>
</body>

</html>

   

vue简单的逻辑 

客户端页面:

 <div id="app" >
        <ul>
            <li v-for="item in msgList" :key="item.id">
                <p>
                    <span>{{item.username}}:</span>
                    <span>{{new Date(item.dataTime)}}</span>
                </p>
                <p>消息:{{item.msg}}</p>
            </li>
        </ul>
        <input type="text" placeholder="请输入消息" v-model="msg" />
        <button @click="sendMsg">发送</button>
    </div>
<script>
    const ws = new WebSocket('ws://localhost:8000')


    new Vue({
        el: '#app',
        data: {
            msg: '',
            username: '',
            msgList: []

        },
        mounted() {
            ws.addEventListener('open', this.handleWsOpen.bind(this), false) // 监听连接打开 前面的this指向绑定的ws,bind里面的this为了改变指向,指向当前vue实例
            ws.addEventListener('close', this.handleWsClose.bind(this), false) // 监听连接关闭
            ws.addEventListener('error', this.handleWsError.bind(this), false) // 监听连接错误
            ws.addEventListener('message', this.handleWsMessage.bind(this), false) // 监听消息

        },
        methods: {
            sendMsg() {
                //把绑定的消息取出来
                const msg=this.msg
                //如果去掉两边空格,长度还为0,则返回不再进行下一步
             if(!msg.trim().length){
                return
             }

                //把当前时间戳
                const dataTime=new Date().getTime()
                //把用户名
                const username=this.username
                //把消息发送到服务器
                ws.send(JSON.stringify({
                    msg,
                    dataTime,
                    username
                }))
                //不可以传对象 要转化为JSON字符串
                // ws.send({   
                //    id:new Data().getTime(),
                //    user:this.username,
                //    dataTime:new Data().getTime(),
                //    msg:this.msg 
                // })
                this.msg=''   //注意发送完要清空输入框
            },
            handleWsOpen(e) {
                console.log('连接成功')
            },
            handleWsClose(e) {
                console.log('连接关闭')
            },
            handleWsError(e) {
                console.log('连接错误')
            },
            handleWsMessage(event) {
                const data = JSON.parse(event.data)   //内容包裹在data中 且需要转换为对象
                this.msgList.push(data)
                console.log(data)
            }
        }
    })
</script>

 服务器部分:

增加长连接的方式 :

<template>
         <ul>
            <li v-for="item in msgList" :key="item.id">
                <p>
                    <span>{{item.username}}:</span>
                    <span>{{new Date(item.dataTime)}}</span>
                </p>
                <p>消息:{{item.msg}}</p>
            </li>
        </ul>
        <input type="text" placeholder="请输入消息" v-model="msg" />
        <button @click="sendDataToServer">发送</button>
</template>
 
<script>
    export default {
        name: "WebSocket",
        data() {
            return {                
                wsIsRun: false,     // ws是否启动              
                webSocket: null,    // 定义ws对象                
                ws: '',             // ws请求链接(类似于ws后台地址)
                wsTimer: null,      // ws定时器
                msg: '',
                username: '',
                msgList: [],       //包含传过去的id,username,dataTime
            }
        },
        async mounted() {
            this.wsIsRun = true
            this.wsInit()
        },
        methods: {
            sendDataToServer() {
                if (this.webSocket.readyState === 1) {
                   // this.webSocket.send('来自前端的数据')
                 //把绑定的消息取出来
                const msg = this.msg
                //如果去掉两边空格,长度还为0,则返回不再进行下一步
                if (!msg.trim().length) {
                    return
                }
                //当前时间戳
                const dataTime = new Date().getTime()
                //用户名
                const username = this.username
                //把消息发送到服务器
                this.webSocket.send(JSON.stringify({
                    msg,
                    dataTime,
                    username
                }))
                 this.msg = ''   //注意发送完要清空输入框
                } else {
                    throw Error('服务未连接')
                }
            },
            /**
             * 初始化ws
             */
            wsInit() {
                const wsuri = 'ws://10.229.36.158:7777/websocket/badao'
                this.ws = wsuri
                if (!this.wsIsRun) return
                // 销毁ws
                this.wsDestroy()
                // 初始化ws
                this.webSocket = new WebSocket(this.ws)
                // ws连接建立时触发
                this.webSocket.addEventListener('open', this.wsOpenHanler)
                // ws服务端给客户端推送消息
                this.webSocket.addEventListener('message', this.wsMessageHanler)
                // ws通信发生错误时触发
                this.webSocket.addEventListener('error', this.wsErrorHanler)
                // ws关闭时触发
                this.webSocket.addEventListener('close', this.wsCloseHanler)
 
                // 检查ws连接状态,readyState值为0表示尚未连接,
               //  1表示建立连接,2正在关闭连接,3已经关闭或无法打开
                clearInterval(this.wsTimer)
                this.wsTimer = setInterval(() => {
                    if (this.webSocket.readyState === 1) {
                        clearInterval(this.wsTimer)
                    } else {
                        console.log('ws建立连接失败')
                        this.wsInit()
                    }
                }, 3000)
            },
            wsOpenHanler(event) {
                console.log('ws建立连接成功')
            },
            wsMessageHanler(e) {
                console.log(e)
                const data = JSON.parse(e.data)   //内容包裹在data中 且需要转换为对象
                this.msgList.push(data)
            },
            /**
             * ws通信发生错误
             */
            wsErrorHanler(event) {
                console.log(event, '通信发生错误')
                this.wsInit()
            },
            /**
             * ws关闭
             */
            wsCloseHanler(event) {
                console.log(event, 'ws关闭')
                this.wsInit()
            },
            /**
             * 销毁ws
             */
            wsDestroy() {
                if (this.webSocket !== null) {
                    this.webSocket.removeEventListener('open', this.wsOpenHanler)
                    this.webSocket.removeEventListener('message', this.wsMessageHanler)
                    this.webSocket.removeEventListener('error', this.wsErrorHanler)
                    this.webSocket.removeEventListener('close', this.wsCloseHanler)
                    this.webSocket.close()
                    this.webSocket = null
                    clearInterval(this.wsTimer)
                }
            },
        }
    }
</script>
 
<style scoped>
 
</style>

页面布局:

:style="i.userId == userId? 'float: right' : '' "   

:class="i.userId == userId? 'right':'left'"  

可用于区分聊天内容在左侧还是右侧

.left {
          background: white;
          animation: toLeft 0.5s ease both 1;
        }
        .right {
          background: #53a8ff;
          color: white;
          animation: toright 0.5s ease both 1;
        }
        @keyframes toLeft {
          0% {
            opacity: 0;
            transform: translateX(-10px);
          }
          100% {
            opacity: 1;
            transform: translateX(0px);
          }
        }
        @keyframes toright {
          0% {
            opacity: 0;
            transform: translateX(10px);
          }
          100% {
            opacity: 1;
            transform: translateX(0px);
          }
        }
      }
    }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值