关于socket实时双向通讯总结

354 阅读3分钟

介绍

最近正在做一个关于websocket实时双向通讯的聊天App 所用到的技术栈是socket.io实现实时双向通讯,在使用的过程中遇到一些问题 通过看一些大佬的文章和阅读文档 总结了一下常用的知识点 有不对的的地方 各位大佬多指教

方法一:

  • 服务端使用ws
  • 客户端使用原生websocket

ws是一种简单易用、快速且经过全面测试的Web套接字客户端和服务器实现。

/*
    1.服务端安装ws   npm i ws -S
    2.引入ws 
    3.使用node运行文件
*/import { WebSocketServer } from "ws"; 
//创建一个wbsocket服务实例对象
const server = new WebSocketServer({ port: 3000 });  

server.on('connection',socket => {    
  //向每一个连接的客户端发送这条消息
  socket.send(JSON.stringify({    
   type:'我是服务端发送过来的消息'
  }))
  
  //获取客户端发送过来的消息
  socket.on('message',data => {    
    let Data = JSON.parse(data)
    console.log(Data);   // { type: '我是客户端发送的消息' }
  })
  
  //监听客户端断开
  socket.on('close',()=> {
    console.log('客户端断开连接');   
  })
})
// 客户端wbsocket
const socket = new WebSocket('ws://localhost:8000')
socket.addEventListener('open',() =>{    //一旦建立连接,向服务器发送这条消息
     socket.send(JSON.stringify({
           type:'我是客户端发送的消息'
     }))
 })
 //客户端建立连接通过监听 message 事件来获取
socket.addEventListener('message',({data}) => { 
     console.log(JSON.parse(data));  //{type:'我是服务端发送过来的消息'}
 })

方法二:

  • 服务端使用socket.io
  • 客户端使用socket.io-client

与上面相似使用方法不同 Socket.IO 提供了附加功能,这些功能隐藏了在生产环境中运行基于 WebSockets 的应用程序的复杂性、

/*
    1.服务端安装 npm i socket.io-client
    2.创建实例 通过socket.emit()发送事件     socket.on() 监听事件
*/const Server = require('socket.io');
const io = new Server(3000);
io.on('connection',socket =>{
    //发射msg事件传递数据
    socket.emit('msg',1,(res) => {
        console.log(res)   //我是回调函数
    })
    //监听客户端发射的事件
    socket.on('send',data => {
        console.log(data)   //{name:'我是客户端传递给服务端的数据'}
    })
})

注意:版本不能相差太大 否则可能造成连接上了 而无法推送数据

/*
    1.客户端安装 npm i socket.io-client
    2.创建实例 通过socket.emit()发送事件     socket.on() 监听事件
*/
<script src="../node_modules/socket.io-client/dist/socket.io.js"></script>
const socket = io('http://localhost:3000')
socket.on('msg',(data,callback) => {   //监听客户端事件
    console.log(args)  // 1
    callback('我是回调函数')s
})
socket.emit('send',{name:'我是客户端传递给服务端的数据'})
​
​

在服务器端,您可以向所有连接的客户端客户端的子集发送事件:

// to all connected clients
io.emit("hello");
​
// to all connected clients in the "news" room
io.to("news").emit("hello");

命名空间允许您在单个共享连接上拆分应用程序的逻辑。例如,如果您想创建一个只有授权用户才能加入的“管理员”频道,这可能很有用。

io.on("connection", (socket) => {
  // classic users
});
​
io.of("/admin").on("connection", (socket) => {
  // admin users
});

服务器端

io.on("connection", (socket) => {
​
  //基本发射
  socket.emit(/* ... */);
​
  // 发送给当前命名空间中除发件人以外的所有客户端
  socket.broadcast.emit(/* ... */);
​
  // 发送给除sende以外的room1中的所有客户
  socket.to("room1").emit(/* ... */);
​
  // 发送给除发件人以外的room1和/或room2中的所有客户端
  socket.to(["room1", "room2"]).emit(/* ... */);
​
  // 发送room1中的所有客户
  io.in("room1").emit(/* ... */);
​
  // 发送于除3号房间以外的1号房间和/或2号房间的所有客户
  io.to(["room1", "room2"]).except("room3").emit(/* ... */);
​
  // “我的命名空间”中的所有客户端
  io.of("myNamespace").emit(/* ... */);
​
  // 至命名空间“my namespace”中room1中的所有客户端
  io.of("myNamespace").to("room1").emit(/* ... */);
​
  // 至单个socketid(专用消息)
  io.to(socketId).emit(/* ... */);
​
  // 此节点上的所有客户端(使用多个节点时)
  io.local.emit(/* ... */);
​
  // 到所有连接的客户端
  io.emit(/* ... */);
​
  // 指定事件
  socket.emit("question", (answer) => {
    // ...
  });
​
  // 无压缩
  socket.compress(false).emit(/* ... */);
​
  // 如果低级传输不可写,则可能会丢弃的消息
  socket.volatile.emit(/* ... */);
​
  // with timeout
  socket.timeout(5000).emit("my-event", (err) => {
    if (err) {
      // 另一方未在给定延迟内确认事件
    }
  });
});

客户端

//基本发射
socket.emit(/* ... */);
​
// 指定事件
socket.emit("question", (answer) => {
  // ...
});
​
// 无压缩
socket.compress(false).emit(/* ... */);
​
// 如果低级传输不可写,则可能会丢弃的消息
socket.volatile.emit(/* ... */);
​
// with timeout
socket.timeout(5000).emit("my-event", (err) => {
  if (err) {
    // 另一方未在给定延迟内确认事件
  }
});

事件

在每一侧,以下事件是保留的,不应被您的应用程序用作事件名称:

  • connect
  • connect_error
  • disconnect
  • disconnecting
  • newListener
  • removeListener
// 引发错误时
socket.emit("disconnecting");)