Sedbol
@Sedbol

Как данное реализуется?

Как данное реализуется? Решил посмотреть на другом сайте как устроен websocket, для собственного развития.
Сокет там установлен на nodeJs. Одного не могу понять как там устроена схема передачи сообщений?
Дело в следующем:
GET запросом передаю в PHP сообщение и оно приходит в websocket. Как данное происходит?
Код отправки в PHP
add: function(e, i) {
                        var n = {
                            r: e.roomId,
                            m: e.message
                        };	                       
						new t({
                            url: "room/v3/chat/add.php",
                            data: n,
                            methodType: "GET",
                            onComplete: i,
                            beforeSend: e.beforeSend
                        })
                    }
                }

Если делаю GET запрос из строки с другой вкладки, то сообщение приходит в сокет.
GET запрос который посылаю на этот же сайт
https://site.ru/web/room/v3/chat/add.php?r=10_9&m=1&viewer_id=818031&auth_key=fad7b&ts=1580009929722&client_type=1

Не пойму как при отправки в PHP сообщение приходит в сокет? То есть нахожусь на сайти отправляю с другой вкладки сообщение GET запросом, и оно приходит websocket? И при отправке в PHP сразу же появляется в чате. Что за фокус такой?
  • Вопрос задан
  • 181 просмотр
Решения вопроса 1
zoonman
@zoonman
⋆⋆⋆⋆⋆
Реализуется достаточно просто.
У вас один nodejs процесс слушает TCP порт 80. Браузер может создавать множество соединений с сервером, как короткоживущих, вроде GET/POST, так и долговременных, как WebSockets.
Websockets используют механизм апгрейда соединения, суть которого заключается в изменении самого протокола верхнего уровня при установлении TCP соединения. Простыми словами, сначала веб-сокеты цепляются по обычному HTTP, потом шлют заголовки Upgrade: WebSocket и Connection: Upgrade, после чего штаны (http) превращаются в элегантные брюки (websockets).
Поэтому один и тот же сервер может обслуживать и веб-сокеты и http. На этом заканчивается магия одновременных соединений со стороны браузере с одним и тем же сервером по разным протоколам. Дальше начинается магия того, как передаются данные с одного протокола (http) в веб-сокет.
Поскольку чат работает внутри одного процесса (это я нарочно упрощаю), то у процесса есть разделяемый обработчик событий. Через него сообщения пересылаются между обработчиками разных протоколов.

В коде очень упрощенно это выглядит так:
// импортируем зависимости

import app from 'express';
import { createServer } from 'http';
import socketio from 'socket.io';

// наш http сервер
const app = express();
const http = createServer(app);

// наш websocket сервер
const io = socketio(http);

// глобальная шина сообщений
const messageBus = new EventEmitter();

// так мы получаем сообщение по http
app.get('/message', (req, res) => {
	console.log('http message:', req.params);
	// и пихаем его дальше по шине сообщений
	messageBus.emit('message', req.params);
})

// когда установлено соединение, 
// мы можем настроить подписку на сообщения
io.on('connection', (socket) => {
	// соединение установлено!
	console.log('Connected!');

	// так мы подписываемся на сообщение
	// приходящее через вебсокеты
	socket.on('message', (message) => {
		console.log('websockets message:', message);
		// и шлем его дальше по шине сообщений
		messageBus.emit('message', message);
	});

	// теперь мы подписываемся на любые сообщения
	// вне зависимости от того, откуда они были получены,
	// и пересылаем их всем через вебсокеты
	messageBus.on('message', (message) => {
		io.emit('message', message);
	});

});

// слушаем по http порт 3000
http.listen(3000, () => {
  console.log('запустились на порту 3000');
});


В реальной жизни вместо разделяемого объекта EventEmitter используется реальная шина сообщений на основе Redis Pub/Sub или очередей, вроде RabbitMQ. Такие штуки делаются для очень больших чатов, способных держать десятки и сотни тысяч человек онлайн. Например чаты в масштабах Youtube, Twitch и т.д.
Для небольших чатов до несколько десятков тысяч пользователей вполне достаточно одного хорошо написанного сервера на Go.
Nodejs не подходит для высоконагруженных проектов ввиду очевидно высокого уровня потребления ресурсов.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы