什么是socket.Io?

SocketIO是在客户端和服务端之间建立的双向通信数据交换技术,底层使用EngineIO。SocketIO的的客户端使用Engine.IO-Client,服务端使用Engine.IO实现。

Socket.Io如何工作

当一个浏览器尝试建立SocketIO时,SocketIO首先使用xhr-polling创建一个长轮询。长轮询一旦建立,它将升级为WebSocket连接。

SocketIO底层是使用EngineIO库实现的,这个库使用WebSocket和XMLHttprequest封装了一套自己的Socket协议(暂时叫 EIO Socket)。一个完整的 EIO Socket 包括多个 XHR 和 WebSocket 连接.

客户端

EIO Socket 通过一个 XHR (XMLHttprequest) 握手。前端发送一个 XHR,告诉服务端我要开始 XHR 长轮询了。后端返回的数据里面包括一个 open 标志(数字 0 表示), 以及sid 和 upgrades 字段,ping时间间隔,ping超时时间。

0{
"sid": "8b7ab1ae-fbcf-4d23-8192-3c14a2a90721",
"upgrades": [
"websocket"
],
"pingInterval": 10000,
"pingTimeout": 60000
}

服务端

服务端使用 ws 库实现 WebSocket 协议。http://socket.io 服务启动时,会先启动一个 ws 服务。http://socket.io 会监听 HTTP 服务器的 upgrade 和 request 事件。当 upgrade 事件触发时,说明可能是 WebSocket 握手,先简单校验下,然后把请求交给 ws 服务进行处理,拿到 WebSocket 对象。当 request 事件触发时,根据 url 路径判断是不是 http://socket.io 的 XHR 请求,拿到 res 和 res 对象。这样就可以正确接收和返回客户端数据了,具体处理过程和前端部分是对应的。

示例一SocketIO进行聊天

服务器
服务器需要安装node.js,我们使用Express简化设置
使用以下命令创建一个新文件夹:

mkdir socket.io-example

cd socket.io-example

npm install socket.io express

安装服务器并导入所需的程序包。

const app = require("express")();

const http = require("http").createServer(app);

const io = require("socket.io")(http);

将服务器根目录设置为index.html

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

设置SocketIO的链接建立事件,这里我们只打印一条log

io.on("connection", function(socket) { console.log(“socket connected”); });

设置服务器侦听端口为3000

http.listen(3000, () => console.log("listening on http://localhost:3000"));

运行命令node index.js,然后在浏览器中打开页面。

客户端

在页面上导入SocketIO脚本

<script src="/socket.io/socket.io.js"></script> <script> const socket =io.connect("http://127.0.0.1:1234/easemob",{path: "/socket.io/"}); </script>

这样,便建立起了一个SocketIO连接。

服务器

在服务器内部,我们使用io.emit()向所有连接的客户端发送消息,当有用户连接到服务器时,以下代码将对所有服务器进行通知,包括连接者本人。

io.on("connection", function(socket) { io.emit(“user connected”); });

如果你想向除了连接者之外的所有人广播,你可以使用

socket.broadcast.emit()。

在此基础上,我们还可以对客服端发送的消息添加监听器,并将响应消息发送给所有用户。

io.on("connection", function(socket) {
 io.emit(“user connected”); socket.on(“message", function(msg) {
  io.emit("message", msg);
}); 
});

以下实例显示了怎么将这些事件添加到客户端。

客户端

在index.html中引入我们的脚本,同时创建简单的表单消息和显示消息的容器。

<html>
 <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>Socket.io Example</title>
 </head>
 
 <body>
   <h1>Our Socket.io Chat Application</h1>
   <div>
     <h2>Messages</h2>
     <ul></ul>
   </div>
   <form action="">
     <input type="text" />
     <button>Send</button>
   </form>
   <script src="/socket.io/socket.io.js"></script>
   <script>
     const socket = io();
   </script>
 </body>
</html>

再添加一些其他逻辑

<script>
 const form = document.querySelector("form");
 const input = document.querySelector("input");
 messageList = document.querySelector("ul");
  const socket = io();
  function sendMessage(e) {
  e.preventDefault();
  socket.emit("message", input.value);
  input.value = "";
 }
  form.addEventListener("submit", sendMessage);
  
  function addMessageToHTML(message) {
  
   const li = document.createElement("li");
   
   li.innerText = message;
   
   messageList.append(li);
 }
  
 socket.on("message", addMessageToHTML);
  function alertUserConnected() {
   addMessageToHTML("User connected");
 }
 socket.on("user connected", alertUserConnected);
 
</script>

这其中最重要的是socket.on(event,callback)功能。当服务器发出的事件与我们设置的’event’匹配时,将触发回调,这时将在屏幕上显示消息。