1. Предпосылки
Некоторое время назад одноклассник из «Планеты знаний» попросил меня поделиться WebSocket, когда я был свободен.Если не учитывать основные детали уровня протокола, то в основном одно или два предложения могут прояснить ситуацию:
WebSocket построен на транспортном уровне TCP и опирается на протокол прикладного уровня HTTP, который, по-видимому, в основном компенсирует дефект протокола HTTP, заключающийся в том, что сервер не может активно отправлять сообщения клиенту.
Но просто так отвечать, я не думаю, что это очень полезно для одноклассника, лучше воплотить это в жизнь и построить реальный пример.
Пример описания: Мобильный телефон может установить связь с компьютером путем сканирования QR-кода компьютера (на самом деле это не обязательно должен быть мобильный телефон для управления компьютером, если он является сквозным), а затем щелкните квадрат на мобильном телефоне, чтобы синхронно управлять квадратом на компьютере.
Пример опыта:портал
Во-вторых, реализация идей
- Сначала сторона ПК должна установить соединение со стороной сервера.После установления соединения сервер создает уникальный идентификатор для подключенного экземпляра и возвращает его клиенту. В то же время сохраняется карта для сохранения экземпляра соединения с идентификатором соединения в качестве значения ключа.
- Сторона ПК получает идентификатор соединения, объединяет URL-адрес страницы контроллера с идентификатором в качестве параметра и генерирует URL-адрес в виде QR-кода, что удобно для сканирования мобильного телефона.
- Мобильный телефон сканирует код для доступа к объединенному URL-адресу на стороне ПК, получает идентификатор связанной стороны из параметра URL-адреса и инициирует соединение с сервером.Когда соединение успешно установлено, связанный идентификатор отправляется на службы, сервер получает соответствующее сообщение и поддерживает карту для создания нового идентификатора экземпляра.Отношения с идентификатором связанной стороны
- Когда мобильный терминал нажимает на поле, он отправляет сообщение на сервер, и сервер находит экземпляр связанной стороны и прозрачно передает сообщение на ПК-терминал.
- Сторона ПК выполняет соответствующие действия согласно прозрачному сообщению
3. Реализация кода
1) Серверный код
Создайте службу WebSocket с помощью экспресс
const app = express();
// 创建应用服务器
const server = http.createServer(app);
// 启动 HTTP 服务
server.listen(port, '0.0.0.0', function onStart(err) {
if (err) {
console.log(err);
}
console.log('启动成功');
});
// 通过 ws 模块建立 Websocket 服务器
const WebSocketServer = require('ws').Server;
const wss = new WebSocketServer( { server : server } );
// 连接实例 Map
process.wsMap = {}
// 连接实例关联关系 Map
process.wsRelaMap = {}
// 连接监听
require('./src/socket/conn.js')(wss)
Для удобства здесь используется модуль узла ws, специально разработанный для работы с WebSocket.Как упоминалось ранее, WebSocket зависит от HTTP, поэтому при установке сервера WebSocket необходимо передать экземпляр HTTP-сервера. После того, как сервер успешно установлен, ему необходимо прослушивать подключения от клиента:
wss.on('connection', function( ws ) {
// 连接实例 id
const id = ws._ultron.id;
ws.on('message', function( data, flags ) {
const dataStr = data;
data = JSON.parse(data);
/**
* 初始连接,并且传入了需要关联的 id
*/
if (data.type === '1' && data.relaId) {
wsRelaMap[id] = data.relaId;
} else if (data.type === '2') { // 发送消息到关联方
const rela = wsMap[wsRelaMap[id]];
if (rela) {
rela.send(dataStr);
}
}
});
// 连接关闭,从 Map 中移除,否则长期占据内存
ws.on('close', function() {
console.log('stopping client');
delete wsMap[id]
});
// 保持连接实例
wsMap[id] = ws;
// 发送 id 到客户端
ws.send(message.buildConnectMessage(id));
});
Тип сообщения различается в зависимости от типа соединения.Для начального сообщения о соединении тип равен 1. Если передается идентификатор связанной стороны, это устанавливает отношение ассоциации. Когда тип равен 2, найдите связанную сторону экземпляра и прозрачно передайте сообщение связанной стороне.
2) Код на стороне ПК (контролируемая сторона)
установить соединение
var domain = '192.168.1.102:5001/';
var wsServer = 'ws://' + domain;
var websocket = new WebSocket(wsServer);
получить сообщение
function onMessage (evt) {
// console.log(evt.data)
// document.getElementById('message').innerText = evt.data
var msg = JSON.parse(evt.data);
var qrcodeImg = document.getElementById('qrcodeImg');
console.log(msg);
console.log(msg.id);
// 消息类型为1,初始化连接的时候,服务器端返回连接 id
if (msg.type === '1') {
// 拼接控制方连接,并调用接口生成二维码
qrcodeImg.src = 'http://qr.liantu.com/api.php?text=http://' + domain + 'handler.html?id=' + msg.id
} else {
// 其它类型的消息为控制消息,根据消息做相应的变换
qrcodeImg.style.display = 'none';
document.getElementById('show').style.display = 'block';
if (msg.selected) {
var items = document.getElementsByClassName('item');
for (var i=0; i <items.length; i++) {
items[i].style.backgroundColor = '#ccc'
}
document.getElementById(msg.selected).style.backgroundColor = 'red'
}
}
}
Когда начальное соединение установлено, сервер вернет идентификатор экземпляра соединения (отличите тип сообщения в соответствии с полем типа), а внешний интерфейс соединит ссылку контроллера в соответствии с идентификатором и вызовет интерфейс для генерации QR-кода. . Для управляющих сообщений после разбора достаточно изменить цвет соответствующего квадрата.
3) Интерфейсный контроллер
После того, как соединение будет открыто, получите идентификатор ассоциации из URL-адреса, отправьте его на сервер для установления ассоциации и прослушивания кликов по сетке и отправьте управляющее сообщение на сервер в любое время.
function onOpen () {
// 获取关联 id
var relaId = getQueryString('id') || 1
var message = {
type: '1',
relaId: relaId
};
// 发起关联消息
websocket.send(JSON.stringify(message));
var conMsg = {
type: '2',
message: 'connected'
};
websocket.send(JSON.stringify(conMsg));
// 监听点击,改变方格颜色,并发起控制消息
var items = document.getElementsByClassName('item');
for (var i=0; i <items.length; i++) {
items[i].addEventListener('click', function (e) {
var msg = {
type: '2',
selected: this.id
};
websocket.send(JSON.stringify(msg));
for (var i=0; i <items.length; i++) {
items[i].style.backgroundColor = '#ccc';
}
this.style.backgroundColor = 'red';
});
}
}
4. Резюме
Для конечной цели этот пример слишком прост, мы можем сделать и более крутые вещи, например: цветы перекатываются с мобильного телефона А на мобильный телефон Б, только вы не можете придумать, нет ничего, что мы не могли бы попробовать ~~
мы вПланета знаний Fima Front-endЗапущен план совместного строительства демонстраций WebSocket, искренне приглашаем вас присоединиться и летать вместе