Разница между веб-сокетами и Socket.IO
Доброго времени суток, друзья!
Веб-сокеты и Socket.IO, вероятно, являются двумя наиболее распространенными средствами коммуникации в режиме реального времени (далее — живое общение). Но чем они отличаются?
При построении приложения для живого общения наступает момент, когда необходимо выбрать средство для обмена данными между клиентом и сервером. Веб-сокеты и Socket.IO являются самыми популярными средствами живого общения в современном вебе. Какое из них выбрать? В чем разница между этими технологиями? Давайте выясним.
Веб-сокеты
Говоря о веб-сокетах, мы имеем ввиду протокол веб-коммуникации, представляющий полнодуплексный канал коммуникации поверх простого TCP-соединения. Проще говоря, эта технология позволяет установить связь между клиентом и сервером с минимальными затратами, позволяя создавать приложения, использующие все преимущества живого общения.
Например, представьте, что вы создаете чат: вам необходимо получать и отправлять данные как можно быстрее, верно? С этим прекрасно справляются веб-сокеты! Вы можете открыть TCP-соединение и держать его открытым сколько потребуется.
Веб-сокеты появились в 2010 году в Google Chrome 4, первый RFC (6455) опубликован в 2011.
Веб-сокеты используются в следующих случаях:
Socket.IO
Socket.IO — библиотека JavaScript, основанная (написанная поверх) на веб-сокетах… и других технологиях. Она использует веб-сокеты, когда они доступны, или такие технологии, как Flash Socket, AJAX Long Polling, AJAX Multipart Stream, когда веб-сокеты недоступны. Легкой аналогией может служить сравнение Fetch API и Axios.
Разница между веб-сокетами и Socket.IO
Главными преимуществами Socket.IO является следующее:
Во-первых, веб-сокеты поддерживаются всеми современными браузерами. Поэтому вы редко нуждаетесь в поддержке других технологий, предоставляемой Socket.IO.
Если говорить о сетевом трафике, то веб-сокеты отправляют всего два запроса:
В npm существует пакет «websocket-vs-socket.io», который позволяет сравнить сетевой трафик этих технологий:
Сетевой трафик веб-сокетов:
Сетевой трафик Socket.IO:
Пишем код
Простой сервер на веб-сокетах
В нашей программе на Node.js мы создадим сервер, работающий на порту 3001. При каждом подключении клиента мы будем присваивать ему уникальный ID. При отправке сообщения клиентом мы будем уведомлять его об успехе: [ ]:
Отлично! Но что если мы хотим рассылать сообщение каждому подключенному клиенту? Веб-сокеты не поддерживают рассылку по умолчанию. Это можно реализовать следующим образом:
Легко и просто! Как видите, WebSocket.Server хранит записи о каждом подключенном клиенте, поэтому мы можем сделать итерацию и отправить сообщение каждому. Вы можете протестировать код на компьютере (MacOS) или в браузере (Chrome).
Простой сервер на Socket.IO
Это было не сложно. Может ли Socket.IO сделать это еще проще? Как нам написать такой же сервер на Socket.IO?
Код получился почти наполовину короче! Как видите, метод «broadcast» не отправляет уведомление отправителю, поэтому мы вынуждены делать это вручную.
Существует проблема: код нельзя протестировать на обычном клиенте веб-сокетов. Это связано с тем, что, как отмечалось ранее, Socket.IO использует не чистые веб-сокеты, а множество технологий для поддержки всех возможных клиентов. Так как же нам проверить его работоспособность?
Необходимо использовать специальный клиент. В приведенном примере мы загружаем его из CDN. Этот клиент позволяет нам провести быстрые (грязные) тесты в браузере.
Сокеты в Python для начинающих
Предисловие
В далеком для меня 2010 году я писал статью для начинающих про сокеты в Python. Сейчас этот блог канул в небытие, но статья мне показалась довольно полезной. Статью нашел на флешке в либровском документе, так что это не кросспост, не копипаст — в интернете ее нигде нет.
Что это
Для начала нужно разобраться что такое вообще сокеты и зачем они нам нужны. Как говорит вики, сокет — это программный интерфейс для обеспечения информационного обмена между процессами. Но гораздо важнее не зазубрить определение, а понять суть. Поэтому я тут постараюсь рассказать все как можно подробнее и проще.
Существуют клиентские и серверные сокеты. Вполне легко догадаться что к чему. Серверный сокет прослушивает определенный порт, а клиентский подключается к серверу. После того, как было установлено соединение начинается обмен данными.
Рассмотрим это на простом примере. Представим себе большой зал с множеством небольших окошек, за которыми стоят девушки. Есть и пустые окна, за которыми никого нет. Те самые окна — это порты. Там, где стоит девушка — это открытый порт, за которым стоит какое-то приложение, которое его прослушивает. То есть, если, вы подойдете к окошку с номером 9090, то вас поприветствуют и спросят, чем могут помочь. Так же и с сокетами. Создается приложение, которое прослушивает свой порт. Когда клиент устанавливает соединение с сервером на этом порту именно данное приложение будет ответственно за работу этим клиентом. Вы же не подойдете к одному окошку, а кричать вам будут из соседнего 🙂
После успешной установки соединения сервер и клиент начинают обмениваться информацией. Например, сервер посылает приветствие и предложение ввести какую-либо команду. Клиент в свою очередь вводит команду, сервер ее анализирует, выполняет необходимые операции и отдает клиенту результат.
Сервер
Сейчас создайте два файла — один для сервера, а другой для клиента.
В Python для работы с сокетами используется модуль socket:
Прежде всего нам необходимо создать сокет:
Здесь ничего особенного нет и данная часть является общей и для клиентских и для серверных сокетов. Дальше мы будем писать код для сервера. Это вполне логично — зачем нам писать клиентское приложение, если некуда подключаться 🙂
Теперь нам нужно определиться с хостом и портом для нашего сервера. Насчет хоста — мы оставим строку пустой, чтобы наш сервер был доступен для всех интерфейсов. А порт возьмем любой от нуля до 65535. Следует отметить, что в большинстве операционных систем прослушивание портов с номерами 0 — 1023 требует особых привилегий. Я выбрал порт 9090. Теперь свяжем наш сокет с данными хостом и портом с помощью метода bind, которому передается кортеж, первый элемент (или нулевой, если считать от нуля) которого — хост, а второй — порт:
Теперь у нас все готово, чтобы принимать соединения. С помощью метода listen мы запустим для данного сокета режим прослушивания. Метод принимает один аргумент — максимальное количество подключений в очереди. Напряжем нашу бурную фантазию и вспомним про зал с окошками. Так вот этот параметр определяет размер очереди. Если он установлен в единицу, а кто-то, явно лишний, пытается еще подстроится сзади, то его пошлют 🙂 Установим его в единицу:
Ну вот, наконец-то, мы можем принять подключение с помощью метода accept, который возвращает кортеж с двумя элементами: новый сокет и адрес клиента. Именно этот сокет и будет использоваться для приема и посылке клиенту данных.
Вот и все. Теперь мы установили с клиентом связь и можем с ним «общаться». Т.к. мы не можем точно знать, что и в каких объемах клиент нам пошлет, то мы будем получать данные от него небольшими порциями. Чтобы получить данные нужно воспользоваться методом recv, который в качестве аргумента принимает количество байт для чтения. Мы будем читать порциями по 1024 байт (или 1 кб):
Как мы и говорили для общения с клиентом мы используем сокет, который получили в результате выполнения метода accept. Мы в бесконечном цикле принимаем 1024 байт данных с помощью метода recv. Если данных больше нет, то этот метод ничего не возвращает. Таким образом мы можем получать от клиента любое количество данных.
Дальше в нашем примере для наглядности мы что-то сделаем с полученными данными и отправим их обратно клиенту. Например, с помощью метода upper у строк вернем клиенту строку в верхнем регистре.
Теперь можно и закрыть соединение:
Собственно сервер готов. Он принимает соединение, принимает от клиента данные, возвращает их в виде строки в верхнем регистре и закрывает соединение. Все просто 🙂 В итоге у вас должно было получиться следующее:
Клиент
Думаю, что теперь будет легче. Да и само клиентское приложение проще — нам нужно создать сокет, подключиться к серверу послать ему данные, принять данные и закрыть соединение. Все это делается так:
Думаю, что все понятно, т.к. все уже разбиралось ранее. Единственное новое здесь — это метод connect, с помощью которого мы подключаемся к серверу. Дальше мы читаем 1024 байт данных и закрываем сокет.
Что такое сокет сетевые технологии
Сетевые сокеты — способ взаимодействия любого приложения с системой на которой оно работает. Сокет — это интерфейс, который по сути представляет собой совокупность адреса в сети и используемого порта. Также часто термин употребляется применительно к Socket API, о котором рассказывается во второй части статьи.
Клиентское приложение всегда работает на локальной машине, подключенной к сети
Интерфейс между приложением и хост-машиной (Network-Application Interface) определяет как приложение может использовать сеть.
Сетевые сокеты и клиент серверная модель
Приложение клиента (посылает например URL в случае с вебом или запрос к MySQL) на определенный сетевой адрес и порт. В примере это localhost и порт 3306 — сервер в свою отвечает приложению. К приложению при этом могут обращаться множество клиентов, запросы и использованием сокета приходят на один и тот же адрес и обрабатываются одним пакетом. Таким образом работает клиент-серверая модель взаимодействия.
Чтобы написать приложение, которое могло бы обслуживать множество клиентов (последовательно и параллельно) нужно сокет API
Socket API — интерфейс используемый всеми интернет приложениями.
Socket API при соединении 2-х приложений может работать с потоками и с датаграммами :
Сетевой сокет — комбинация IP адреса и номера порта, которые представляют собой способ адресации и обеспечивают нормальное взаимодействие большого количества приложений в рамках одной системы.
Один сокет не может использовать два приложения одновременно или два экземпляра одного приложения.
Вызовы в Socket API
SOCKET — вызов создает структуру
BIND — связывает локальный адрес с сокетом
LISTEN — заявляет о готовности установить соединение
ACCEPT — принимает входящее соединение
CONNECT — пробует установить соединение
SEND — отправляет данные в рамках соединения
RECEIVE — принимает информацию в рамках соединения
CLOSE — прерывает соединение
Интерфейс сокетов в транспортном уровне — операции сокетов Беркли
Интерфейс применяется для взаимодействия между разными уровнями.
Транспортный уровень (ТУ) это первый уровень с которым может взаимодействовать программист. Поэтому интерфейс ТУ, который позволяет нам писать программы для сети, мы обязательно будем рассматривать.
Сокеты Беркли
Интерфейс называется интерфейсом сокетов. Сокеты впервые появились в операционной системе (ОС) Berkeley Unix 4.2 BSD в 1983 году.
Там сокеты, как и любые другие устройства в UNIX это просто файл, специального типа. Вы пишите данные в этот файл, они автоматически передаются по сети на другой компьютер. Другой компьютер может прочитать данные оттуда, как из обычного файла. Хотя, на самом деле они пришли по сети.
Таким образом взаимодействие с сетью скрыто от программиста. Такая абстракция оказалась очень удобной, сокеты стали использоваться не только в UNIX, но и во многих других ОС в том числе в windows и linux, поддержку сокетов добавили во многие языки программирования.
Сокеты сейчас это де-факто стандарт для взаимодействия программ с транспортным уровнем, стека протоколов TCP/IP.
Операции сокетов Беркли
МЫ будем рассматривать операции сокетов Беркли. Большая часть современных реализаций сокетов имеют такие же операции или очень похожие на них.
Операции сокетов Беркли делятся на несколько типов.
Модель клиент-сервер
Сокеты Беркли используют модель клиент-сервер. Сервер это программа, которая постоянно работает на некотором компьютере, известен его IP адрес и порт и сервер ждет подключение клиентов. А клиент это приложение, которое активно устанавливает соединение с сервером.
Работа сокетов
Рассмотрим подробнее, как используются сокеты Беркли. У нас есть два компьютера, клиент и сервер. Вначале необходимо создать сокет на сервере и сделать так, чтобы он мог принимать запрос на соединение.
На сервере выполняется вызов Soket. Создается объект — сокет, в простейшем случае, это просто файл специального вида.
Затем вызывается метод Bind, который используется для присоединения сокета к определенному ip адресу и порту. Например, ip адрес из внутренней сети и порт 80, порт веб серверов.
Вызов Listen говорит о том, что сокет готов принимать соединение по сети, сокет слушает. При вызове listen создаётся очередь для соединений, в вызове необходимо указать размер этой очереди. В примере на картинке ниже, размер очереди 5. Если сервер получит больше, чем 5 запросов на соединение, а предыдущие запросы еще не обработаны, то все новые запросы будут отбрасываться.
Затем сервер вызывает метод сокета accept, это говорит о том, что сервер готов принимать соединения и он переходит в режим пассивного ожидания, ждет установку запросов на соединение от клиентов.
Клиент со свой стороны, сначала вызывает метод сокет, для создания сокета, как правило для клиента не имеет значение, какой ip адрес и какой порт используется, номер порта назначается операционной системой. Поэтому метод bind на клиентском сокете обычно не вызывается.
Сразу после создания сокета, вызывается метод connect, в котором указывается ip адрес и порт. В параметрах метода connect указываются ip адрес сервера и порт с которыми нужно установить соединение. Отправляется запрос на соединение.
Для того, чтобы другие клиенты могли соединяться с этим сервером на этом ip адресе и на этом же порту, создаётся копия сокета. И соединение устанавливается не с исходным сокетом, который принимает соединения, а с копией сокета. Данные передаются через копию сокета.
Клиент подготавливает порцию данных, вызывает метод send. Данные передаются по сети и сервер может их прочитать с помощью метода receive.
Дальше сервер и клиент могут обмениваться между собой несколькими порциями данных. После того, как все данные переданы, клиент вызывает метод close. После чего происходит разрыв соединения.
Видео пример на Python. Серверный сокет
Рассмотрим пример применения сокетов для разработки программы на питон. Это популярный сейчас язык на котором очень удобно писать программы для работы сетей. Конечно существует большое количество других языков на которых можно писать программу для сетей, но работа с сокетами везде будет примерно одинаковая.
Посмотри видео о примере сокета на языке питон. (timecode 5:15)
Python. Типы сокетов
Рассмотрим более подробно, какие виды протоколов можно использовать в сокетах. На сетевом уровне можно использовать:
Есть и другие типы сокетов, но с сетями TCP/IP они используются редко.
Пример на Python. Клиентский сокет
Рассмотрим использование сокетов на стороне клиентов. Также посмотри видео, которое указано выше. (Timecode 7:03)
Заключение
Сокеты это De-facto стандарт интерфейса транспортного уровня. Именно сокеты необходимо использовать, чтобы писать программы для сетей, которые взаимодействуют напрямую с транспортным уровнем. Хотя сейчас многие программы взаимодействуют не с транспортным уровнем, а прикладным уровнем, который предоставляет больше возможностей.
Программирование сокетов. Сеть и сокет
Web Sockets (веб-сокеты) — это технология, позволяющая создавать интерактивное соединение для обмена сообщения в онлайн-режиме. Соединение создаётся в сети между сервером и клиентом (браузером). В отличие от протокола HTTP, веб-сокеты позволяют работать с 2-направленным потоком данных, поэтому можно с уверенностью сказать, что технология является уникальной. Для наилучшего понимания давайте разберём особенности работы сокетов и посмотрим, а чем они конкретно отличаются от HTTP.
Как функционирует HTTP?
Про протокол HTTP (HTTPS) знает каждый, так как мы постоянно встречаемся с ним в своих браузерах. Как правило, браузер постоянно запрашивает у сервера, есть ли для него сообщения, а потом получает их. Здесь возможны различные типы запросов (POST, GET, PUT), причём каждый из них имеет своё назначение. Особенности работы хорошо видны на картинке:
А что сокеты?
Сокет для ответа не нуждается в ваших повторяющихся запросах. Сокет в сети работает таким образом, что достаточно лишь один раз выполнить запрос, а потом ждать отклика. И вы можете спокойно «слушать» сервер, который отправит сообщения по мере готовности.
Когда используют веб-сокет?
Сокет применяется в том случае, если вы, к примеру, разрабатываете: — чат- и IoT-приложения; — программы, работающие в режиме реального времени; — многопользовательские игры.
Когда нежелательно применять сокет?
Особых противопоказаний в отношении сокета и сокетов нет. Один из недостатков — несовместимость с некоторыми видами браузеров, но этот минус уже практически изжил себя, так как сегодня около 95 % браузеров поддерживают сокеты.
Тем не менее иногда сокет вам всё же не нужен, и зависит это от того, с каким типом приложения вы будете работать. Например, вы создаёте простую CMS и вам совершенно нет нужды обеспечивать функциональность в режиме реального времени.
Не стоит применять сокет и в REST API, так как будет вполне достаточно стандартных HTTP-запросов (GET, DELETE, POST и PUT). В целом специалисты не рекомендует использовать сокет, если это не риалтайм-приложение, но вопрос о недостатках сокетов требует более детального рассмотрения в рамках отдельной статьи.
От теории к практике
Давайте напишем сокет самостоятельно. Для создания клиента будем использовать язык программирования JavaScript, а для создания сервера — Node.js.
Собственно говоря, мы подобрали максимально простые примеры, которые в первую очередь нужны для того, чтобы разобраться в сути такой технологии, как сокет.
Cоздание клиента
Cоздание сервера
И что в итоге?
Что же, давайте продемонстрируем работу созданных нами сокетов:
Есть ли эквивалент сокету в HTTP?
В принципе, есть. Смотрите, HTTP должен проверять канал в сети на наличие новых сообщений. Следовательно, мы можем задействовать dirty check, то есть «грязную проверку». При этом подходе клиент с заданной периодичностью (например, каждые 100 мс) будет проверять, есть ли новые сообщения на сервере. Не вникая в XMLHttpRequest, можно применять библиотеку Axios. Это достаточно понятный и декларативный инструмент. Итак, наш клиент:
А теперь посмотрим, что делается на сервере:
Делаем выводы
Можно с уверенностью заявить, что сокет — довольно перспективная веб-технология, поэтому уже сейчас её использует множество разработчиков. Кроме того, сокеты прекрасно подходят для взаимодействия в реальном времени, включая онлайн-игры.