socket.io 简介

1,074 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第3天,点击查看活动详情

什么是 socket.io

socket.io 是一个由 JavaScript 实现、基于 Node.js 、支持 WebSocket 协议用于实时通信、跨平台的开源框架,它包括了客户端 JavaScript 及服务端 Node.js 。也就是 socket.io 将 WebSocket 和轮询机制封装成通用接口,并在服务端实现了这些通讯机制。

Node.js 中使用 socket.io

第一步:准备客户端文件 index.html,初始化 socket 连接,监听服务端 receive server 推送信息:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>

</head>
<body>
<h1> socket test</h1>
</body>
<script src="https://cdn.bootcdn.net/ajax/libs/socket.io/4.4.1/socket.io.js"></script>
<script>
    const socket = io("http://localhost:8081");
    socket.on("receive server", (data) => {
        console.log(data)
    })
</script>
</html>

第二步:准备服务端 node.js 的 app.js 文件,首先是启动 http 服务返回上述 html 文件(不使用同一域名,会出现跨域问题);监听创建连接时的 connection 事件,并向客户端触发 receive server 事件:

const http = require("http");
const fs = require("fs");
const socketio = require("socket.io");
const server = http.createServer((req, res) => {
    fs.readFile(__dirname + "/index.html", (err, data) => {
        if (err) {
            console.log(err);
        } else {
            res.writeHead(200, {
                "Content-Type": "text/html;charset=utf-8"
            });
            res.write(data);
            res.end();

        }
    })
}).listen(8081)
const io = socketio(server)
io.on("connection", socket => {
    console.log("connect");
    socket.emit("receive server", "hello world");
    
})

node app.js 运行程序,浏览器打开 http://localhost:8081,查看控制台输出:

image.png

socket.io 实现聊天室

由于 socket 支持服务端直接向客户端推送,故 socket 十分适合用于开发聊天室。

首先,使用 express 作为服务器,npm i express@4

const express = require('express');
const app = express();
const http = require('http');
const server = http.createServer(app);
const { Server } = require("socket.io");
const io = new Server(server);

app.get('/', (req, res) => {
  res.sendFile(__dirname + '/index.html');
});

io.on('connection', (socket) => {
  console.log('a user connected');
});

server.listen(3000, () => {
  console.log('listening on *:3000');
});

index.html 的代码如下:

<!DOCTYPE html>
<html>

<head>
    <title>Socket.IO chat</title>
    <style>
        body {
            margin: 0;
            padding-bottom: 3rem;
            font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
        }

        #form {
            background: rgba(0, 0, 0, 0.15);
            padding: 0.25rem;
            position: fixed;
            bottom: 0;
            left: 0;
            right: 0;
            display: flex;
            height: 3rem;
            box-sizing: border-box;
            backdrop-filter: blur(10px);
        }

        #input {
            border: none;
            padding: 0 1rem;
            flex-grow: 1;
            border-radius: 2rem;
            margin: 0.25rem;
        }

        #input:focus {
            outline: none;
        }

        #form>button {
            background: #333;
            border: none;
            padding: 0 1rem;
            margin: 0.25rem;
            border-radius: 3px;
            outline: none;
            color: #fff;
        }

        #messages {
            list-style-type: none;
            margin: 0;
            padding: 0;
        }

        #messages>li {
            padding: 0.5rem 1rem;
        }

        #messages>li:nth-child(odd) {
            background: #efefef;
        }
    </style>
</head>

<body>
    <ul id="messages"></ul>
    <form id="form" action="">
        <input id="input" autocomplete="off" /><button>Send</button>
    </form>
</body>
<script src="https://cdn.bootcdn.net/ajax/libs/socket.io/4.4.1/socket.io.min.js"></script>
<script>
    var socket = io();
</script>
</html>

运行 node app.js,打开多个标签页的 http://localhost:3000 ,控制台输出如下信息:

image.png

每次打开新的标签页,都会触发一次 connection 事件,服务端每个 socket 还可以触发特殊回调 disconnect

客户端新增表单提交事件,触发 chat message 提交信息,同时监听 chat message 推送:

var socket = io();
var form = document.getElementById('form');
var input = document.getElementById('input');

form.addEventListener('submit', function (e) {
    e.preventDefault();
    if (input.value) {
        socket.emit('chat message', input.value);
        input.value = '';
    }
});
socket.on('chat message', function (msg) {
    var item = document.createElement('li');
    item.textContent = msg;
    messages.appendChild(item);
    window.scrollTo(0, document.body.scrollHeight);
});

服务端监听 chat message 并广播通知所有客户端:

io.on('connection', (socket) => {
    socket.on('chat message', (msg) => {
        io.emit('chat message', msg);
    });
});

这样,一个简易的 socket.io 聊天室就完成了~

image.png

参考

socket.io 官方文档