第120题 WebSocket和HTTP协议有什么区别

  • 支持端对端通信
  • 可由client发起,也可由sever发起
  • 用于消息通知、直播间讨论区、聊天室、协同编辑

WebSocket连接过程

  • 先发起一个HTTP请求
  • 成功之后在升级到WebSocket协议,再通讯

WebSocket和HTTP区别

  • WebSocket协议名是ws://,可双端发起请求(双端都可以sendonmessage
  • WebSocket没有跨域限制
  • 通过sendonmessage通讯(HTTP通过reqres

WebSocket和HTTP长轮询的区别

长轮询:一般是由客户端向服务端发出一个设置较长网络超时时间的 HTTP 请求,并在Http连接超时前,不主动断开连接;待客户端超时或有数据返回后,再次建立一个同样的HTTP请求,重复以上过程

  • HTTP长轮询:客户端发起请求,服务端阻塞,不会立即返回
    • HTTP长轮询需要处理timeout,即timeout之后重新发起请求
  • WebSocket:客户端可发起请求,服务端也可发起请求

ws可升级为wss(像https)

    import {createServer} from 'https'
    import {readFileSync} from 'fs'
    import {WebSocketServer} from 'ws'
    
    const server = createServer({
      cert: readFileSync('/path/to/cert.pem'),
      key: readFileSync('/path/to/key.pem'),
    })
    const wss = new WebSocketServer({ server })

实际项目中推荐使用socket.io API更简洁

    io.on('connection',sockert=>{
      // 发送信息
      socket.emit('request', /**/)
      // 广播事件到客户端
      io.emit('broadcast', /**/)
      // 监听事件
      socket.on('reply', ()=>{/**/})
    })

WebSocket基本使用例子

    // server.js
    const { WebSocketServer } = require('ws') // npm i ws 
    const wsServer = new WebSocketServer({ port: 3000 })
    
    wsServer.on('connection', ws => {
      console.info('connected')
    
      ws.on('message', msg => {
        console.info('收到了信息', msg.toString())
    
        // 服务端向客户端发送信息
        setTimeout(() => {
          ws.send('服务端已经收到了信息: ' + msg.toString())
        }, 2000)
      })
    })
    <!-- websocket main page -->
    <button id="btn-send">发送消息</button>
    
    <script>
        const ws = new WebSocket('ws://127.0.0.1:3000')
        ws.onopen = () => {
          console.info('opened')
          ws.send('client opened')
        }
        ws.onmessage = event => {
          console.info('收到了信息', event.data)
        }
    
        document.getElementById('btn-send').addEventListener('click', () => {
          console.info('clicked')
          ws.send('当前时间' + Date.now())
        })
    </script>

创建简易聊天室

    // server.js
    
    const { WebSocketServer } = require('ws') // npm i ws 
    const wsServer = new WebSocketServer({ port: 3000 })
    
    const list = new Set()
    
    wsServer.on('connection', curWs => {
      console.info('connected')
    
      // 这里,不能一直被 add 。实际使用中,这里应该有一些清理缓存的机制,长期用不到的 ws 要被 delete
      list.add(curWs)
    
      curWs.on('message', msg => {
        console.info('received message', msg.toString())
    
        // 传递给其他客户端
        list.forEach(ws => {
          if (ws === curWs) return
          ws.send(msg.toString())
        })
      })
    })

client1

    <!-- client 1-->
    
    <p>websocket page 1</p>
    <button id="btn-send">发送消息</button>
    
    <script>
      const ws = new WebSocket('ws://127.0.0.1:3000')
      ws.onopen = () => {
        console.info('opened')
        ws.send('client1 opened')
      }
      ws.onmessage = event => {
        console.info('client1 received', event.data)
      }
    
      document.getElementById('btn-send').addEventListener('click', () => {
        console.info('clicked')
        ws.send('client1 time is ' + Date.now())
      })
    </script>

client2

    <!-- client 2-->
    
    <p>websocket page 2</p>
    <button id="btn-send">发送消息</button>
    
    <script>
      const ws = new WebSocket('ws://127.0.0.1:3000')
      ws.onopen = () => {
        console.info('opened')
        ws.send('client2 opened')
      }
      ws.onmessage = event => {
        console.info('client2 received', event.data)
      }
    
      document.getElementById('btn-send').addEventListener('click', () => {
        console.info('clicked')
        ws.send('client2 time is ' + Date.now())
      })
    </script>
Last Updated:
Contributors: leeguooooo