- Сокеты в Python для начинающих
- Предисловие
- Что это
- Сервер
- Клиент
- Сокеты в ОС Linux
- Что такое сокет?
- netcat
- socat
- Разница между веб-сокетами и Socket.IO
- Веб-сокеты
- Socket.IO
- Разница между веб-сокетами и Socket.IO
- Сетевой трафик веб-сокетов:
- Сетевой трафик Socket.IO:
- Пишем код
- Простой сервер на веб-сокетах
- Простой сервер на Socket.IO
Сокеты в Python для начинающих
Предисловие
В далеком для меня 2010 году я писал статью для начинающих про сокеты в Python. Сейчас этот блог канул в небытие, но статья мне показалась довольно полезной. Статью нашел на флешке в либровском документе, так что это не кросспост, не копипаст — в интернете ее нигде нет.
Что это
Для начала нужно разобраться что такое вообще сокеты и зачем они нам нужны. Как говорит вики, сокет — это программный интерфейс для обеспечения информационного обмена между процессами. Но гораздо важнее не зазубрить определение, а понять суть. Поэтому я тут постараюсь рассказать все как можно подробнее и проще.
Существуют клиентские и серверные сокеты. Вполне легко догадаться что к чему. Серверный сокет прослушивает определенный порт, а клиентский подключается к серверу. После того, как было установлено соединение начинается обмен данными.
Рассмотрим это на простом примере. Представим себе большой зал с множеством небольших окошек, за которыми стоят девушки. Есть и пустые окна, за которыми никого нет. Те самые окна — это порты. Там, где стоит девушка — это открытый порт, за которым стоит какое-то приложение, которое его прослушивает. То есть, если, вы подойдете к окошку с номером 9090, то вас поприветствуют и спросят, чем могут помочь. Так же и с сокетами. Создается приложение, которое прослушивает свой порт. Когда клиент устанавливает соединение с сервером на этом порту именно данное приложение будет ответственно за работу этим клиентом. Вы же не подойдете к одному окошку, а кричать вам будут из соседнего 🙂
После успешной установки соединения сервер и клиент начинают обмениваться информацией. Например, сервер посылает приветствие и предложение ввести какую-либо команду. Клиент в свою очередь вводит команду, сервер ее анализирует, выполняет необходимые операции и отдает клиенту результат.
Сервер
Сейчас создайте два файла — один для сервера, а другой для клиента.
В Python для работы с сокетами используется модуль socket:
Прежде всего нам необходимо создать сокет:
Здесь ничего особенного нет и данная часть является общей и для клиентских и для серверных сокетов. Дальше мы будем писать код для сервера. Это вполне логично — зачем нам писать клиентское приложение, если некуда подключаться 🙂
Теперь нам нужно определиться с хостом и портом для нашего сервера. Насчет хоста — мы оставим строку пустой, чтобы наш сервер был доступен для всех интерфейсов. А порт возьмем любой от нуля до 65535. Следует отметить, что в большинстве операционных систем прослушивание портов с номерами 0 — 1023 требует особых привилегий. Я выбрал порт 9090. Теперь свяжем наш сокет с данными хостом и портом с помощью метода bind, которому передается кортеж, первый элемент (или нулевой, если считать от нуля) которого — хост, а второй — порт:
Теперь у нас все готово, чтобы принимать соединения. С помощью метода listen мы запустим для данного сокета режим прослушивания. Метод принимает один аргумент — максимальное количество подключений в очереди. Напряжем нашу бурную фантазию и вспомним про зал с окошками. Так вот этот параметр определяет размер очереди. Если он установлен в единицу, а кто-то, явно лишний, пытается еще подстроится сзади, то его пошлют 🙂 Установим его в единицу:
Ну вот, наконец-то, мы можем принять подключение с помощью метода accept, который возвращает кортеж с двумя элементами: новый сокет и адрес клиента. Именно этот сокет и будет использоваться для приема и посылке клиенту данных.
Вот и все. Теперь мы установили с клиентом связь и можем с ним «общаться». Т.к. мы не можем точно знать, что и в каких объемах клиент нам пошлет, то мы будем получать данные от него небольшими порциями. Чтобы получить данные нужно воспользоваться методом recv, который в качестве аргумента принимает количество байт для чтения. Мы будем читать порциями по 1024 байт (или 1 кб):
Как мы и говорили для общения с клиентом мы используем сокет, который получили в результате выполнения метода accept. Мы в бесконечном цикле принимаем 1024 байт данных с помощью метода recv. Если данных больше нет, то этот метод ничего не возвращает. Таким образом мы можем получать от клиента любое количество данных.
Дальше в нашем примере для наглядности мы что-то сделаем с полученными данными и отправим их обратно клиенту. Например, с помощью метода upper у строк вернем клиенту строку в верхнем регистре.
Теперь можно и закрыть соединение:
Собственно сервер готов. Он принимает соединение, принимает от клиента данные, возвращает их в виде строки в верхнем регистре и закрывает соединение. Все просто 🙂 В итоге у вас должно было получиться следующее:
Клиент
Думаю, что теперь будет легче. Да и само клиентское приложение проще — нам нужно создать сокет, подключиться к серверу послать ему данные, принять данные и закрыть соединение. Все это делается так:
Думаю, что все понятно, т.к. все уже разбиралось ранее. Единственное новое здесь — это метод connect, с помощью которого мы подключаемся к серверу. Дальше мы читаем 1024 байт данных и закрываем сокет.
Источник
Сокеты в ОС Linux
В данной статье будет рассмотрено понятие сокета в операционной системе Linux: основные структуры данных, как они работают и можно ли управлять состоянием сокета с помощью приложения. В качестве практики будут рассмотрены инструменты netcat и socat.
Что такое сокет?
Сокет — это абстракция сетевого взаимодействия в операционной системе Linux. Каждому сокету соответствует пара IP-адрес + номер порта. Это стандартное определение, к которому привыкли все, спасибо вики. Хотя нет, вот здесь лучше описано. Поскольку сокет является только лишь абстракцией, то связка IP-адрес + номер порта — это уже имплементация в ОС. Верное название этой имплементации — «Интернет сокет». Абстракция используется для того, чтобы операционная система могла работать с любым типом канала передачи данных. Именно поэтому в ОС Linux Интернет сокет — это дескриптор, с которым система работает как с файлом. Типов сокетов, конечно же, намного больше. В ядре ОС Linux сокеты представлены тремя основными структурами:
struct socket — представление сокета BSD, того вида сокета, который стал основой для современных «Интернет сокетов»;
struct sock — собственная оболочка, которая в Linux называется «INET socket»;
struct sk_buff — «хранилище» данных, которые передает или получает сокет;
Как видно по исходным кодам, все структуры достаточно объемны. Работа с ними возможна при использовании языка программирования или специальных оберток и написания приложения. Для эффективного управления этими структурами нужно знать, какие типы операций над сокетами существуют и когда их применять. Для сокетов существует набор стандартных действий:
socket — создание сокета;
bind — действие используется на стороне сервера. В стандартных терминах — это открытие порта на прослушивание, используя указанный интерфейс;
listen — используется для перевода сокета в прослушивающее состояние. Применяется к серверному сокету;
connect — используется для инициализации соединения;
accept — используется сервером, создает новое соединение для клиента;
send/recv — используется для работы с отправкой/приемом данных;
close — разрыв соединения, уничтожение сокета.
Если о структурах, которые описаны выше, заботится ядро операционной системы, то в случае команд по управлению соединением ответственность берет на себя приложение, которое хочет пересылать данные по сети. Попробуем использовать знания о сокетах для работы с приложениями netcat и socat.
netcat
Оригинальная утилита появилась 25 лет назад, больше не поддерживается. На cегодняшний день существуют порты, которые поддерживаются различными дистрибутивами: Debian, Ubuntu, FreeBSD, MacOS. В операционной системе утилиту можно вызвать с помощью команды nc, nc.traditional или ncat в зависимости от ОС. Утилита позволяет «из коробки» работать с сокетами, которые используют в качестве транспорта TCP и UDP протоколы. Примеры сценариев использования, которые, по мнению автора, наиболее интересны:
перенаправление входящих/исходящих запросов;
трансляция данных на экран в шестнадцатеричном формате.
Опробуем операции в действии. Задача будет состоять в том, что необходимо отправить TCP данные через netcat в UDP соединение. Для лабораторной будет использоваться следующая топология сети:
Введем команду на открытие порта на машине Destination: nc -ulvvp 7878
Настроим машину Repeater. Так как передача из одного интерфейса этой машины будет происходить по протоколу TCP, а на другой интерфейс будет осуществляться передача по протоколу UDP, то для таких действий необходимо сделать соединитель, который сможет накапливать данные и пересылать их между открытыми портами. На такую роль отлично подходит FIFO файл. Поэтому команда для запуска будет выглядеть так: sudo mkfifo /tmp/repeater #создать FIFO файл
sudo nc -l -p 4545 > /tmp/repeater | nc -u 10.0.3.5 7878 IP адрес 10.0.3.5 — адрес машины Destination. Символы «|» и «> nc 10.0.2.4 4545
В итоге получаем возможность читать данные от машины Source:
В машине Destination:
Пример с трансляцией данных в шестнадцатеричном формате можно провести так же, но заменить команду на Destination или добавить еще один пайп на Repeater:
nc -l -p 4545 -o file
В результате будет создан файл, в котором можно будет обнаружить передаваемые данные в шестнадцатеричном формате:
Как видно из тестового сценария использования, netcat не дает контролировать практически ничего, кроме направления данных. Нет ни разграничения доступа к ресурсам, которые пересылаются, ни возможности без дополнительных ухищрений работать с двумя сокетами, ни возможности контролировать действия сокета. Протестируем socat.
socat
Инструмент, который до сих пор поддерживается и имеет весьма обширный функционал по склейке каналов для взаимодействия. Разработчиками инструмент именуется как netcat++. Ниже приведем небольшой список того что можно перенаправить через socat:
STDIO -> TCP Socket;
FILE -> TCP Socket;
TCP Socket -> Custom Application;
UDP Socket -> Custom Application;
Для повседневного использования достаточно опций, но если понадобится когда-то работать напрямую с серийным портом или виртуальным терминалом, то socat тоже умеет это делать. Полный перечень опций можно вызвать с помощью команды:
Помимо редиректов socat также можно использовать как универсальный сервер для расшаривания ресурсов, через него можно как через chroot ограничивать привилегии и доступ к директориям системы.
Чтобы комфортно пользоваться этим инструментом, нужно запомнить шаблон командной строки, который ожидает socat:
socat additionalOptions addr1 addr2
additionalOptions — опции, которые могут добавлять возможности логирования информации, управления направлением передачи данных;
addr1 — источник данных или приемник (влияет использование флага U или u), это может быть сокет, файл, пайп или виртуальный терминал;
addr2 — источник данных или приемник (влияет использование флага U или u), это может быть сокет, файл, пайп или виртуальный терминал;
Попробуем провести трансляцию данных из сокета в сокет. Будем использовать для этого 1 машину. Перед началом эксперимента стоит отметить, что особенностью socat является то, что для его корректной работы нужно обязательно писать 2 адреса. Причем адрес не обязательно должен быть адресом, это может быть и приложение, и стандартный вывод на экран.
Например, чтобы использовать socat как netcat в качестве TCP сервера, можно запустить вот такую команду:
socat TCP-LISTEN:4545, STDOUT
Для коннекта можно использовать netcat:
nc localhost 4545
При таком использовании, socat дает возможность пересылать сообщения в обе стороны, но если добавить флаг «-u», то общение будет только от клиента к серверу. Все серверные сообшения пересылаться не будут:
Настроим более тонко наш сервер, добавив новые опции через запятую после используемого действия:
socat TCP-LISTEN:4545,reuseaddr,keepalive,fork STDOUT
Дополнительные параметры распространяются на те действия, которые socat может выполнять по отношению к адресу. Полный список опций можно найти здесь в разделе «SOCKET option group».
Таким образом socat дает практически полный контроль над состоянием сокетов и расшариваемых ресурсов.
Статья написана в преддверии старта курса Network engineer. Basic. Всех, кто желает подробнее узнать о курсе и карьерных перспективах, приглашаем записаться на день открытых дверей, который пройдет уже 4 февраля.
Источник
Разница между веб-сокетами и 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 позволяет отправлять сообщения всем подключенным клиентам. Например, вы пишете чат и хотите уведомлять всех пользователей о подключении нового пользователя. Вы легко можете это реализовать с помощью одной операции. При использовании веб-сокетов, для реализации подобной задачи вам потребуется список подключенных клиентов и отправка сообщений по одному.
- В веб-сокетах сложно использовать проксирование и балансировщики нагрузки. Socket.IO поддерживает эти технологии из коробки.
- Как отмечалось ранее, Socket.IO поддерживает постепенную (изящную) деградацию.
- Socket.IO поддерживает автоматическое переподключение при разрыве соединения.
- С Socket.IO легче работать.
Может показаться, что Socket.IO — лучшее средство для живого общения. Однако существует несколько ситуаций, когда лучше использовать веб-сокеты.
Во-первых, веб-сокеты поддерживаются всеми современными браузерами. Поэтому вы редко нуждаетесь в поддержке других технологий, предоставляемой Socket.IO.
Если говорить о сетевом трафике, то веб-сокеты отправляют всего два запроса:
- GET для получения HTML страницы
- UPGRADE для соединения с веб-сокетами
Это позволяет установить соединение с сервером. А что насчет Socket.IO?
- GET для получения HTML страницы
- Клиентская библиотека Socket.IO (207кб)
- Три long polling (длинные опросы) Ajax-запроса
- UPGRADE для соединения с веб-сокетами
В мире JS 207кб — это много. Какое нерациональное использование сетевого трафика!
В 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. Этот клиент позволяет нам провести быстрые (грязные) тесты в браузере.
Источник