实时通信 websocket 聊天室

如何让客户端和服务器端能够进行双向通信呢?以前我们可能会使用短轮询啊,长轮询,但这其实并不是真正意义上的双向通信,而是我们在不断的向服务器发送请求,那后来HTML5提供了一个新的API WebSocket,这也让我们的服务器端能够主动给客户端发送消息成为可能。

短轮询:

每隔一段时间比如 1s 钟 向服务器发送一次请求,问服务器是否有人给我们发送信息

弊端: 如果没有人发送消息,还是在不断的轮询,浪费用户流量

长轮询:

只是相对于短轮询,减少了请求次数
比如: 设置请求的超时时间为 5 分钟,那 5 分钟中内如果有消息发送给我们,
那就响应给我们,连接断掉,等我们处理完数据之后再重新发送请求
如果 5 分钟内还没有人发送消息给我们,那就请求超时,连接断掉,我再重新发

websocket:

跟服务器建立连接,打开了一个通信通道,除非客户端或者服务端主动关,否则连接不会关掉
有的浏览器可能不支持 websocket ,就使用 window.websocket 判断有没有 这个类,没有的话就使用 长轮询

那接下来我们使用 websocket 来实现一个简单的聊天室,这里我们使用 ws 插件,它对 websocket 进行了封装,我们使用更加方便

服务器端下载 ws

npm install ws

服务器端:

构建websocket通信服务器

const WebSocket = require('ws');
const server = new WebSocket.Server({
  port: 8000
});

监听客户端的连接

server.on('connection', (socket)=>{
  console.log('有人上线了');
  ......
})

监听客户端发送的信息

socket.on('message', (data)=>{   
    console.log(data); 
    ......
    // 告诉其他的客户端该客户端发了什么信息
  })

客户端:

连接 websocket 服务器

var websocket = new WebSocket('ws://localhost:8000');

成功连接时

websocket .on('open', function open() {
  console.log('connected');
});

断线时

  websocket.onerror = ()=>{
    console.log('断线了');
  }

连接关闭时

  websocket.onclose = ()=>{
    console.log('下线了');
  }

接收到消息时

websocket.onmessage = (ev)=>{
    console.log('接收到了信息:', ev.data);
      // 这个时候可以对接收到的消息做一定处理,比如展示到页面上等
  }

效果如下
在这里插入图片描述
代码实现:

client.html 聊天室的页面

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>聊天室</title>
  <style>
    *{
      margin: 0;
      padding: 0;
    }
    html, body{
      width: 100%;
      height: 100%;
    }
    .panel{
      width: 100%;
      position: absolute;
      top: 0;
      left: 0;
      bottom: 150px;
      border-bottom: 2px solid #ddd;
      padding: 20px;
      box-sizing: border-box;
      overflow: auto;
    }
    .handle{
      width: 100%;
      height: 150px;
      position: absolute;
      bottom: 0;
      left: 0;
    }
    textarea{
      width: 100%;
      height: 100px;
      outline: none;
    }
    button{
      float: right;
      height: 50px;
      line-height: 50px;
      padding: 0 20px;
    }
    .row{
      clear: both;
      max-width: 70%;
      margin: 10px 0;
      padding: 10px;
      border-radius: 5px;
    }
    .left{
      float: left;
      background: lemonchiffon;
    }
    .right{
      float: right;
      background: lavender;
    }
  </style>
</head>
<body>

  <div class="panel">
    <div class="row left">
        <h3>张三:</h3>
        <p>你好</p>
    </div>
    <div class="row right">
        <h3>我:</h3>
        <p>你好</p>
    </div>
  </div>

  <div class="handle">
    <textarea></textarea>
    <button id="send">发送</button>
  </div>
  
  <script>
  
  var websocket = new WebSocket('ws://localhost:8000');
  websocket.onopen = ()=>{
    console.log('上线了');
  }
  
  websocket.onerror = ()=>{
    console.log('断线了');
  }
  
  websocket.onclose = ()=>{
    console.log('下线了');
  }

  websocket.onmessage = (ev)=>{
    console.log('接收到了信息:', ev.data);
      // 页面布局
    document.querySelector('.panel').innerHTML += `
    <div class="row left">
        <h3>别人:</h3>
        <p>${ev.data}</p>
    </div>
    `;
  }
  // 发送的点击事件
  document.querySelector('#send').onclick = ()=>{
    // 获得用户输入
    let value = document.querySelector('textarea').value;
    if(!value){
      alert('输入不能为空');
    }
    else{
      // 发送给服务器
      websocket.send(value);
      // 页面布局
      document.querySelector('.panel').innerHTML += `
      <div class="row right">
          <h3>我:</h3>
          <p>${value}</p>
      </div>
      `;
      // 情空输入框
      document.querySelector('textarea').value = '';
    }
  }
  </script>
</body>
</html>

server.js 服务器端的代码

// websocket
const WebSocket = require('ws');

// 构建websocket通信服务器
const server = new WebSocket.Server({
  port: 8000
});

const arr = []; // 存放连接的客户端

// 监听客户端的连接
server.on('connection', (socket)=>{
  console.log('有人上线了');
  arr.push(socket);

  socket.on('message', (data)=>{
    //客户端发送的信息
    console.log(data);

    // 告诉其他的客户端该客户端发了什么信息
    arr.forEach(item=>{
      item !== socket && item.send(data);
    })

  })

})

see you ~

发布了25 篇原创文章 · 获赞 35 · 访问量 2424

猜你喜欢

转载自blog.csdn.net/weixin_44691775/article/details/104439156