Программирование сокетов. Сеть и сокет. Что такое сокет?

Web Sockets (веб-сокеты) — это технология, позволяющая создавать интерактивное соединение для обмена сообщения в онлайн-режиме. Соединение создаётся в сети между сервером и клиентом (браузером). В отличие от протокола HTTP веб-сокеты позволяют работать с 2-направленным потоком данных, поэтому можно с уверенностью сказать, что технология является уникальной. Для наилучшего понимания давайте разберём особенности работы сокетов и посмотрим, а чем они конкретно отличаются от HTTP.

Как функционирует HTTP?

Про протокол HTTP (HTTPS) знает каждый, так как мы постоянно встречаемся с ним в своих браузерах. Как правило, браузер постоянно запрашивает у сервера, есть ли для него сообщения, а потом получает их. Здесь возможны различные типы запросов (POST, GET, PUT), причём каждый из них имеет своё назначение. Особенности работы хорошо видны на картинке:

1-20219-487645.jpg

А что сокеты?

Сокет для ответа не нуждается в ваших повторяющихся запросах. Сокет в сети работает таким образом, что достаточно лишь один раз выполнить запрос, а потом ждать отклика. И вы можете спокойно «слушать» сервер, который отправит сообщения по мере готовности.

2-20219-310ff7.jpg

Когда используют веб-сокет?

Сокет применяется в том случае, если вы, к примеру, разрабатываете: — чат- и IoT-приложения; — программы, работающие в режиме реального времени; — многопользовательские игры.

Когда нежелательно применять сокет?

Особых противопоказаний в отношении сокета и сокетов нет. Один из недостатков — несовместимость с некоторыми видами браузеров, но этот минус уже практически изжил себя, так как сегодня около 95 % браузеров поддерживают сокеты.

Тем не менее иногда сокет вам всё же не нужен, и зависит это от того, с каким типом приложения вы будете работать. Например, вы создаёте простую CMS и вам совершенно нет нужды обеспечивать функциональность в режиме реального времени.

Не стоит применять сокет и в REST API, так как будет вполне достаточно стандартных HTTP-запросов (GET, DELETE, POST и PUT). В целом специалисты не рекомендует использовать сокет, если это не риалтайм-приложение, но вопрос о недостатках сокетов требует более детального рассмотрения в рамках отдельной статьи.

От теории к практике

Давайте напишем сокет самостоятельно. Для создания клиента будем использовать язык программирования JavaScript, а для создания сервера — Node.js.

Собственно говоря, мы подобрали максимально простые примеры, которые в первую очередь нужны для того, чтобы разобраться в сути такой технологии, как сокет.

Cоздание клиента

<!DOCTYPE html>
<html>
<head>
  <title>Пример чата с сокетом</title>
</head>
<body>
  <script>
    let ws = new WebSocket("ws://localhost:8080");
    // выведем новые сообщения в нашу консоль
    ws.onmessage = ({data}) => {
      console.log(data);
    }
    // отправим сообщение 
    ws.onopen = () => ws.send('Text');
  </script>
</body>
</html>

Cоздание сервера

const WebSocket = require('ws');

// создаём новый сокет-сервер
const wss = new WebSocket.Server({
  port: 8080
});

//  отправляем клиентам, если функция `clientValidator` возвращает true. This — это wss.
wss.broadcast = function(data, clientValidator = () => true) {
  this.clients.forEach(client => {
    if (clientValidator(client)) {
      client.send(data);
    }
  });
}

wss.on("connection", ws => {
  // событие вызовется, если клиент отправит сообщение
  ws.on('message', message => {
    //  отправим сообщение всем за исключением автора
    wss.broadcast(message, client => client !== ws);
  });
});

И что в итоге?

Что же, давайте продемонстрируем работу созданных нами сокетов:

ezgif_2_4d36463f43b7-20219-bcdf7d.gif

Есть ли эквивалент сокету в HTTP?

В принципе, есть. Смотрите, HTTP должен проверять канал в сети на наличие новых сообщений. Следовательно, мы можем задействовать dirty check, то есть «грязную проверку». При этом подходе клиент с заданной периодичностью (например, каждые 100 мс) будет проверять, есть ли новые сообщения на сервере. Не вникая в XMLHttpRequest, можно применять библиотеку Axios. Это достаточно понятный и декларативный инструмент. Итак, наш клиент:

<!DOCTYPE html>
<html>
<head>
  <title>Обмениваемся сообщениями в режиме онлайн</title>
</head>
<body>
  <script src="https://unpkg.com/axios/dist/axios.min.js"></script> 
  <script>
    let localMessages = [];

    // первоначальное обновление локального сообщения 
    axios.get('http://localhost:8080/messages')
    .then(({data}) => localMessages = data.messages);

    // обновление списка сообщений
    const updateMessages = () => {
    axios.get('http://localhost:8080/messages')
      .then(({data}) => {
        const difference = data.messages.splice(localMessages.length);
        difference.forEach(message => {
          console.log(message);
          localMessages.push(message);
        });
      })
      .catch(console.log);
    }

    // отправка сообщения
    const sendMessage = text => {
        axios.post('http://localhost:8080/messages', {text});
    }
    // каждые 100 мс проверяем, присутствуют ли новые сообщения
    setInterval(updateMessages, 100);
  </script>
</body>
</html>

А теперь посмотрим, что делается на сервере:

const express = require('express');
const bodyParser = require('body-parser');
const app = express();

app.use(bodyParser.json(), function(req, res, next) {
  res.header("Access-Control-Allow-Origin", "*");
  res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
  next();
});

// в реальном приложении сообщения сохранялись бы в БД либо в JSON-файлах
// но не в переменной, которая, как известно, обнуляется в случае остановки сервера
let messages = [];

// создается новое сообщение
app.post('/messages', (req, res) => {
  messages.push(req.body.text);
  res.json({
    success: true
  });
});

// получаем все сообщения
app.get('/messages', (req, res) => {
  res.json({
    messages
  });
});

// «слушаем» все запросы на localhost: 8080.
app.listen(8080, () => console.log('Слушаю порт 8080'));

Делаем выводы

Можно с уверенностью заявить, что сокет — довольно перспективная веб-технология, поэтому уже сейчас её использует множество разработчиков. Кроме того, сокеты прекрасно подходят для взаимодействия в реальном времени, включая онлайн-игры.

А что вы думаете про сокет? Пишите в коментариях!

Автор
0 комментариев
Для комментирования необходимо авторизоваться