什么是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’匹配时,将触发回调,这时将在屏幕上显示消息。