что такое socket в сетях

TCP и UDP сокеты в CODESYS V3

CPM723-01: Рекомендации к применению

что такое socket в сетях. main. что такое socket в сетях фото. что такое socket в сетях-main. картинка что такое socket в сетях. картинка main.

Сопроводительные документы

Сокеты и стек протоколов TCP/IP

что такое socket в сетях. pic1. что такое socket в сетях фото. что такое socket в сетях-pic1. картинка что такое socket в сетях. картинка pic1.

Рис. 1. Пример протоколов стека TCP/IP в соответствии с моделью OSI

В распределенных системах управления обмен данными является одним из ключевых моментов работы системы. Контроллер CPM723-01 позволяет отправлять и получать данные по промышленному протоколу Modbus TCP на базе протокола TCP/IP с использованием двух портов Ethernet и по протоколу Modbus RTU/ACSII на базе последовательных сетей RS-485/ RS-232 с помощью коммуникационных модулей NIM741/NIM742. Кроме того, система исполнения контроллера CPM723-01 поддерживает механизм сетевого обмена данными между контроллерами, принадлежащими одной подсети, средствами специального протокола прикладного уровня CODESYS V3.

Иногда возникает необходимость использовать протоколы низкого уровня, которые позволяют обмениваться большим количеством сообщений с помощью стека TCP/IP. Также, на базе них можно создавать протоколы более высокого уровня модели OSI (рис. 1).

Взаимодействие между устройствами в рамках стека TCP/IP осуществляется с помощью связки IP адреса и порта.

Для заданияIP адресав настоящее время чаще всего используется протокол IPv4. Для него IP-адрес записывается в виде 32-битной формы, представляемой в символьной форме mmm.nnn.ppp.qqq: адрес, разбитый на четыре поля, разделённых точками, по одному байту в поле, например, 192.168.102.101. Номер порта задается в диапазоне от 0 до 65535.

Пара адрес и порт образует сокет (с английского socket – «гнездо»). Сокет – является программным интерфейсом, который обеспечивает обмен данными между устройствами на низком уровне (рис. 2).

что такое socket в сетях. pic2. что такое socket в сетях фото. что такое socket в сетях-pic2. картинка что такое socket в сетях. картинка pic2.

Рис. 2. Общение с помощью сокетов.

Протокол TCP/IP основывается на соединениях, устанавливаемых между двумя компьютерами, обычно называемых клиентом и сервером. Поэтому, различают сокет клиента и сокет сервера. Для организации общения клиент должен знать IP адрес и номер порта сервера, по которым он подключается к удаленному устройству. в рамках стека протоколов TCP/IP различают два типа сокетов TCP и UDP. Также, TCP сокеты называют потоковыми, а UDP – датаграммными.

Протокол TCP/IP основывается на соединениях, устанавливаемых между двумя компьютерами, обычно называемых клиентом и сервером. Поэтому, различают сокет клиента и сокет сервера. Для организации общения клиент должен знать IP-адрес и номер порта сервера, по которым он подключается к удаленному устройству. в рамках стека протоколов TCP/IP различают два типа сокетов TCP и UDP. Также, TCP сокеты называют потоковыми, а UDP – датаграммными.

TCP сокеты

TCP сокеты используют TCP-соединения, в которых на транспортном уровне (рис. 1) обеспечивается надёжная доставка данных. TCP протокол отвечает за установление и поддержание соединения, сегментацию, доставку и буферизацию данных, упорядочивание и избавление от дублированных TCP-сегментов данных, контроль ошибок и скорости передачи. Схема работы простого TCP сокета представлена на рисунке 3.

Для удобства в качестве функций, указанных на диаграмме, используются функции, из системной библиотеки SysSocket 3.х.x.x, которая позволяет создавать сокеты на устройствах, поддерживающих платформу CODESYS V3 в том числе на контроллере CPM723-01 модульной линейки Fastwel I/O.

Cерверный TCP сокет

Рассмотрим работу серверного сокета (рис. 3). Будем считать, что существует отдельная программа, исполняемая в контроллере, которая организует обмен данными с помощью сокетов.

что такое socket в сетях. pic3. что такое socket в сетях фото. что такое socket в сетях-pic3. картинка что такое socket в сетях. картинка pic3.

Рис. 3. Работа простого TCP сокета

Инициализация сокета

При старте программы происходит инициализация сервера. С помощью функции SysSockCreate() создается системный идентификатор (handle) сокета. Данная функция в качестве входных параметров принимает аргументы, задающие тип и протокол сокета. Для использования TCP протокола функция SysSockCreate() должна принимать следующие входные аргументы:

После успешной привязки к адресу функция SysSockListen() включает прослушивание входящих соединений (ожидание подключений клиентов к серверу). Функцией SysSockListen() также определяется максимальное количество подключений к серверу. Например, если максимальное количество подключений равно 3, и если 3 клиента уже подключились к серверу, то 4-тому будет отказано в подключении.

Обмен данными

После того как сервер включает режим прослушивания, он переходит в рабочий режим и ждет входящие соединения от клиентов. Как только клиент подключается к сокету сервера, с помощью функции SysSockAccept() создается системный идентификатор клиентского сокета hclientSocket и соединение считается открытым:

Серверный сокет принимает сообщения с помощью функции SysSockRecv() :

Затем отправляет данные с помощью функции SysSockSend() :

Обработка новых подключений

После успешных приема и передачи данных может быть реализовано несколько вариантов поведения программы:

Рис. 4. Обработка подключения нового клиента

Закрытие соединения

В рабочем режиме работы серверный сокет всегда остается открытым. Закрытие серверного сокета может происходить при внешнем событии, или при возникновении критических ошибок. Ошибки при создании и работе сокетов отображаются в системном идентификаторе result, который имеет тип структуры RTS_IEC_RESULT. Обозначение кодов ошибок описано в системной библиотеке CmpErrors Interfaces в глобальных константах Errors (рис. 5).
Для закрытии сокетного соединения используется фукнция SysSockClose() :

что такое socket в сетях. pic5. что такое socket в сетях фото. что такое socket в сетях-pic5. картинка что такое socket в сетях. картинка pic5.

Рис. 5. Расшифровка кодов ошибок работы сокетов

Клиентский TCP сокет

Схема работы клиентского сокета отображена на рисунке 3 справа.

Инициализация клиента

Функция SysSockCreate() создает системный идентификатор сокета. Также, как и для сервера, для клиента необходимо создать потоковый сокет:

Зная IP-адрес и порт сервера, клиент с помощью SysSockConnect() подключается к серверному сокету:

Обмен данными

Обмен данными между клиентом и с помощью функций SysSockSend() и SysSockRecv() :

Закрытие соединения

После обмена данными сокет может быть закрыт с помощью с помощью SysSockClose() :

Однако, с точки зрения циклического обмена данными реального времени, каждый раз закрывать и открывать сокет заново неэффективно. Поэтому после успешной установки соединения обмен данными осуществляется в бесконечном цикле.

Особенности сокетов TCP

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

Несмотря на многие преимущества, TCP сокеты имеют и негативные стороны. Например, необходимость поддержания TCP-соединения уменьшает пропускную способность обмена данными в распределенных системах. Также, в системах обмена данными реального времени повторная передача потерянных пакетов может привести к тому, что система получит данные, которые утратили свою актуальность.

UDP сокеты

Все перечисленные недостатки TCP сокетов связаны с особенностью TCP-протокола. Если в системе присутствие данных факторов крайне нежелательно, а гарантированность доставки сообщений не является критичным требованием, то в качестве альтернативы TCP сокетов могут использоваться UDP (датаграммные) сокеты.

UDP сокеты устроены проще, чем TCP. В качестве транспортного уровня используется протокол UDP, который не требует установления соединения и подтверждения приема. Информация пересылается в предположении, что принимающая сторона ее ожидает. Датаграммные сокеты не контролирует ничего, кроме целостности полученных датаграмм. Несмотря на это, UDP сокеты нашли свое применение в системах, где на первом месте стоит именно актуальность данных и их быстрая доставка, а не гарантия доставки каждого сообщения.

Например, сервер в ответ на запросы клиента передает по сети текущие (мгновенные) значения некоторого параметра контролируемого технологического процесса, а клиент формирует управляющий сигнал на основе принятых значений. Если темп опроса сервера клиентом много больше требуемого времени реакции алгоритма управления на изменение значения контролируемого параметра, то потеря одного-двух сообщений от сервера несущественно повлияет на качество формирования управляющего сигнала. В случае использования TCP соединения потерянное сообщение будет автоматически передано повторно, что может привести к получению клиентом неактуального значения контролируемого параметра и к формированию неправильного управляющего сигнала.

Серверный UDP сокет

На рисунке 6 показана схема работы простого UDP сокета.

Инициализация сервера

Также, как в случае TCP сокетов, системный идентификатор UDP сокета создается с помощью функции SysSockCreate() :

Обмен данными

что такое socket в сетях. pic6. что такое socket в сетях фото. что такое socket в сетях-pic6. картинка что такое socket в сетях. картинка pic6.

Рис. 6. Схема работы простого UDP сокета.

Закрытие соединения

После отправки данных, сокет сервера снова переходит к функции SysSockRecvFrom() и остается незакрытым.

Но в случае необходимости серверный сокет можно закрыть аналогично TCP сокету:

Клиентский UDP сокет

Клиент UDP работает аналогично клиентскому сокету TCP за исключением использования функций SysSockSendTo() и SysSockRecvFrom() для отправки и получения сообщений.

Инициализация клиента

Функция SysSockCreate() создает системный идентификатор сокета. Также, как и для сервера, для клиента необходимо создать потоковый сокет:

Обмен данными

В отличие от TCP сокетов, при использовании UDP протокола клиентский сокет не устанавливает соединения с сервером, а сразу после создания клиентского сокета переходит к обмену данными с помощью функций SysSockSendTo() и SysSockRecvFrom() :

Закрытие соединения

После обмена данными сокет может быть закрыт с помощью с помощью SysSockClose() :

Однако, с точки зрения циклического обмена данными реального времени, каждый раз закрывать и открывать сокет заново неэффективно. Поэтому после успешной установки соединения обмен данными осуществляется в бесконечном цикле.

Дополнительные настройки сокетов

На рисунке 3 и 6 показана работа простых серверного и клиентского сокетов. Но на деле, такая простая схема имеет некоторые ограничения и недостатки.

Блокирующий режим

Естественно, такое поведение программы не является безопасным, и при циклическом вызове программы в ПЛК может сработать сторожевой таймер или произойти выход в безопасный режим – контроллер будет считать, что программа зависла.

Подключение несколько клиентов

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

Если хотя бы один сокет клиента готов, например, к отправке данных, SysSockSelect() сообщит об этом программе и соединение с данным клиентом будет установлено. Схема работы серверного сокета с использованием SysSockSelect() показана на рисунке 5.

Функция SysSockSelect() является блокирующей, она возвращает управление, если хотя бы один из проверяемых сокетов готов к выполнению соответствующей операции. Но в качестве настройки в функции можно указать интервал времени, по прошествии которого она вернет управление в любом случае.

что такое socket в сетях. pic7. что такое socket в сетях фото. что такое socket в сетях-pic7. картинка что такое socket в сетях. картинка pic7.

Рис. 7. Схема работы сокетов с использованием функции SysSockSelect()

Программа сокетов для CPM723

В проектах TCP_UDP_Sockets.project и 2xPLCs_Sockets.project, входящих в комплект поставки программного обеспечения Fastwel I/O, реализованы программы TCP сокетов и UDP сокетов на языках ST и CFC стандарта МЭК 61131-3.

Структура проекта TCP_UDP_Sockets.project указана на рисунке 8. В данном проекте реализовано два проекта для UDP и TCP сокетов, для работы в рамках одного контроллера CPM723-01. В первом проекте CPM723_LOCAL_CFC работа сокетов реализована с помощью функциональных блоков, вызываемых в программах (язык CFC). Во втором проекте CPM723_LOCAL_ST работа сокетов реализована в программах (язык ST).

что такое socket в сетях. pic8. что такое socket в сетях фото. что такое socket в сетях-pic8. картинка что такое socket в сетях. картинка pic8.

Рис. 8. Структура проекта TCP_UDP_Sockets.project

В проекте 2xPLCs_Sockets.project реализован пример для двух контроллеров CPM723-01, обменивающихся данными по протоколу TCP. На первом контроллере ClientsTCP реализованы TCP сокеты клиентов, на втором контроллере ServerTCP – TCP сокет сервера. Структура проекта указана на рисунке 9.

что такое socket в сетях. pic9. что такое socket в сетях фото. что такое socket в сетях-pic9. картинка что такое socket в сетях. картинка pic9.

Рис. 8. Структура проекта TCP_UDP_Sockets.project

Заключение

Сокеты отвечают за обмен данными между различными устройствами и процессами. На базе обмена данными по сокетам можно создавать протоколы стека TCP/IP более высокого уровня.

TCP сокеты необходимо там, где требуется надежная доставка сообщений, а скорость передачи данных не критична. UDP сокеты лучше всего использовать там, где нужна эффективность на быстрых сетях с короткими соединениями и данные реального времени, а гарантированность доставки сообщений не нужна.

Источник

Сокеты в ОС Linux

В данной статье будет рассмотрено понятие сокета в операционной системе Linux: основные структуры данных, как они работают и можно ли управлять состоянием сокета с помощью приложения. В качестве практики будут рассмотрены инструменты netcat и socat.

Что такое сокет?

Как видно по исходным кодам, все структуры достаточно объемны. Работа с ними возможна при использовании языка программирования или специальных оберток и написания приложения. Для эффективного управления этими структурами нужно знать, какие типы операций над сокетами существуют и когда их применять. Для сокетов существует набор стандартных действий:

Если о структурах, которые описаны выше, заботится ядро операционной системы, то в случае команд по управлению соединением ответственность берет на себя приложение, которое хочет пересылать данные по сети. Попробуем использовать знания о сокетах для работы с приложениями netcat и socat.

netcat

Оригинальная утилита появилась 25 лет назад, больше не поддерживается. На cегодняшний день существуют порты, которые поддерживаются различными дистрибутивами: Debian, Ubuntu, FreeBSD, MacOS. В операционной системе утилиту можно вызвать с помощью команды nc, nc.traditional или ncat в зависимости от ОС. Утилита позволяет «из коробки» работать с сокетами, которые используют в качестве транспорта TCP и UDP протоколы. Примеры сценариев использования, которые, по мнению автора, наиболее интересны:

перенаправление входящих/исходящих запросов;

трансляция данных на экран в шестнадцатеричном формате.

Опробуем операции в действии. Задача будет состоять в том, что необходимо отправить TCP данные через netcat в UDP соединение. Для лабораторной будет использоваться следующая топология сети:

что такое socket в сетях. image loader. что такое socket в сетях фото. что такое socket в сетях-image loader. картинка что такое socket в сетях. картинка image loader.

В итоге получаем возможность читать данные от машины Source:

что такое socket в сетях. image loader. что такое socket в сетях фото. что такое socket в сетях-image loader. картинка что такое socket в сетях. картинка image loader.

В машине Destination:

что такое socket в сетях. image loader. что такое socket в сетях фото. что такое socket в сетях-image loader. картинка что такое socket в сетях. картинка image loader.

Пример с трансляцией данных в шестнадцатеричном формате можно провести так же, но заменить команду на Destination или добавить еще один пайп на Repeater:

В результате будет создан файл, в котором можно будет обнаружить передаваемые данные в шестнадцатеричном формате:

что такое socket в сетях. image loader. что такое socket в сетях фото. что такое socket в сетях-image loader. картинка что такое socket в сетях. картинка image loader.

Как видно из тестового сценария использования, netcat не дает контролировать практически ничего, кроме направления данных. Нет ни разграничения доступа к ресурсам, которые пересылаются, ни возможности без дополнительных ухищрений работать с двумя сокетами, ни возможности контролировать действия сокета. Протестируем socat.

socat

Инструмент, который до сих пор поддерживается и имеет весьма обширный функционал по склейке каналов для взаимодействия. Разработчиками инструмент именуется как netcat++. Ниже приведем небольшой список того что можно перенаправить через socat:

Для повседневного использования достаточно опций, но если понадобится когда-то работать напрямую с серийным портом или виртуальным терминалом, то socat тоже умеет это делать. Полный перечень опций можно вызвать с помощью команды:

Помимо редиректов socat также можно использовать как универсальный сервер для расшаривания ресурсов, через него можно как через chroot ограничивать привилегии и доступ к директориям системы.

Чтобы комфортно пользоваться этим инструментом, нужно запомнить шаблон командной строки, который ожидает socat:

socat additionalOptions addr1 addr2

Попробуем провести трансляцию данных из сокета в сокет. Будем использовать для этого 1 машину. Перед началом эксперимента стоит отметить, что особенностью socat является то, что для его корректной работы нужно обязательно писать 2 адреса. Причем адрес не обязательно должен быть адресом, это может быть и приложение, и стандартный вывод на экран.

Например, чтобы использовать socat как netcat в качестве TCP сервера, можно запустить вот такую команду:

socat TCP-LISTEN:4545, STDOUT

Для коннекта можно использовать netcat:

При таком использовании, socat дает возможность пересылать сообщения в обе стороны, но если добавить флаг «-u», то общение будет только от клиента к серверу. Все серверные сообшения пересылаться не будут:

что такое socket в сетях. image loader. что такое socket в сетях фото. что такое socket в сетях-image loader. картинка что такое socket в сетях. картинка image loader.

Настроим более тонко наш сервер, добавив новые опции через запятую после используемого действия:

socat TCP-LISTEN:4545,reuseaddr,keepalive,fork STDOUT

Дополнительные параметры распространяются на те действия, которые socat может выполнять по отношению к адресу. Полный список опций можно найти здесь в разделе «SOCKET option group».

Таким образом socat дает практически полный контроль над состоянием сокетов и расшариваемых ресурсов.

Статья написана в преддверии старта курса Network engineer. Basic. Всех, кто желает подробнее узнать о курсе и карьерных перспективах, приглашаем записаться на день открытых дверей, который пройдет уже 4 февраля.

Источник

Сокеты в Python для начинающих

Предисловие

В далеком для меня 2010 году я писал статью для начинающих про сокеты в Python. Сейчас этот блог канул в небытие, но статья мне показалась довольно полезной. Статью нашел на флешке в либровском документе, так что это не кросспост, не копипаст — в интернете ее нигде нет.

что такое socket в сетях. 812cc5493ecb5b91c0f59c317a48d6cd. что такое socket в сетях фото. что такое socket в сетях-812cc5493ecb5b91c0f59c317a48d6cd. картинка что такое socket в сетях. картинка 812cc5493ecb5b91c0f59c317a48d6cd.

Что это

Для начала нужно разобраться что такое вообще сокеты и зачем они нам нужны. Как говорит вики, сокет — это программный интерфейс для обеспечения информационного обмена между процессами. Но гораздо важнее не зазубрить определение, а понять суть. Поэтому я тут постараюсь рассказать все как можно подробнее и проще.

Существуют клиентские и серверные сокеты. Вполне легко догадаться что к чему. Серверный сокет прослушивает определенный порт, а клиентский подключается к серверу. После того, как было установлено соединение начинается обмен данными.

Рассмотрим это на простом примере. Представим себе большой зал с множеством небольших окошек, за которыми стоят девушки. Есть и пустые окна, за которыми никого нет. Те самые окна — это порты. Там, где стоит девушка — это открытый порт, за которым стоит какое-то приложение, которое его прослушивает. То есть, если, вы подойдете к окошку с номером 9090, то вас поприветствуют и спросят, чем могут помочь. Так же и с сокетами. Создается приложение, которое прослушивает свой порт. Когда клиент устанавливает соединение с сервером на этом порту именно данное приложение будет ответственно за работу этим клиентом. Вы же не подойдете к одному окошку, а кричать вам будут из соседнего 🙂

После успешной установки соединения сервер и клиент начинают обмениваться информацией. Например, сервер посылает приветствие и предложение ввести какую-либо команду. Клиент в свою очередь вводит команду, сервер ее анализирует, выполняет необходимые операции и отдает клиенту результат.

Сервер

Сейчас создайте два файла — один для сервера, а другой для клиента.

В Python для работы с сокетами используется модуль socket:

Прежде всего нам необходимо создать сокет:

Здесь ничего особенного нет и данная часть является общей и для клиентских и для серверных сокетов. Дальше мы будем писать код для сервера. Это вполне логично — зачем нам писать клиентское приложение, если некуда подключаться 🙂

Теперь нам нужно определиться с хостом и портом для нашего сервера. Насчет хоста — мы оставим строку пустой, чтобы наш сервер был доступен для всех интерфейсов. А порт возьмем любой от нуля до 65535. Следует отметить, что в большинстве операционных систем прослушивание портов с номерами 0 — 1023 требует особых привилегий. Я выбрал порт 9090. Теперь свяжем наш сокет с данными хостом и портом с помощью метода bind, которому передается кортеж, первый элемент (или нулевой, если считать от нуля) которого — хост, а второй — порт:

Теперь у нас все готово, чтобы принимать соединения. С помощью метода listen мы запустим для данного сокета режим прослушивания. Метод принимает один аргумент — максимальное количество подключений в очереди. Напряжем нашу бурную фантазию и вспомним про зал с окошками. Так вот этот параметр определяет размер очереди. Если он установлен в единицу, а кто-то, явно лишний, пытается еще подстроится сзади, то его пошлют 🙂 Установим его в единицу:

Ну вот, наконец-то, мы можем принять подключение с помощью метода accept, который возвращает кортеж с двумя элементами: новый сокет и адрес клиента. Именно этот сокет и будет использоваться для приема и посылке клиенту данных.

Вот и все. Теперь мы установили с клиентом связь и можем с ним «общаться». Т.к. мы не можем точно знать, что и в каких объемах клиент нам пошлет, то мы будем получать данные от него небольшими порциями. Чтобы получить данные нужно воспользоваться методом recv, который в качестве аргумента принимает количество байт для чтения. Мы будем читать порциями по 1024 байт (или 1 кб):

Как мы и говорили для общения с клиентом мы используем сокет, который получили в результате выполнения метода accept. Мы в бесконечном цикле принимаем 1024 байт данных с помощью метода recv. Если данных больше нет, то этот метод ничего не возвращает. Таким образом мы можем получать от клиента любое количество данных.

Дальше в нашем примере для наглядности мы что-то сделаем с полученными данными и отправим их обратно клиенту. Например, с помощью метода upper у строк вернем клиенту строку в верхнем регистре.

Теперь можно и закрыть соединение:

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

Клиент

Думаю, что теперь будет легче. Да и само клиентское приложение проще — нам нужно создать сокет, подключиться к серверу послать ему данные, принять данные и закрыть соединение. Все это делается так:

Думаю, что все понятно, т.к. все уже разбиралось ранее. Единственное новое здесь — это метод connect, с помощью которого мы подключаемся к серверу. Дальше мы читаем 1024 байт данных и закрываем сокет.

Источник

Начинающему сетевому программисту

В общем, посмотрев на всё это, я решил написать базовую статью по созданию простейшего клиент-сервер приложения на С++ под Windows с детальным описанием всех используемых функций. Это приложение будет использовать Win32API и делать незамысловатую вещь, а именно: передавать сообщения от клиента к серверу и обратно, или, иначе говоря – напишем программу по реализации чата для двух пользователей.

Сразу оговорюсь, что статья рассчитана на начинающих программистов, которые только входят в сетевое программирование под Windows. Необходимые навыки – базовое знание С++, а также теоретическая подготовка по теме сетевых сокетов и стека технологии TCP/IP.

Теория сокетов за 30 секунд для «dummies»

Начну всё-таки немного с теории в стиле «for dummies». В любой современной операционной системе, все процессы инкапсулируются, т.е. скрываются друг от друга, и не имеют доступа к ресурсам друг друга. Однако существуют специальные разрешенные способы взаимодействия процессов между собой. Все эти способы взаимодействия процессов можно разделить на 3 группы: (1) сигнальные, (2) канальные и (3) разделяемая память.

Для того, чтобы сокеты заработали под Windows, необходимо при написании программы пройти следующие Этапы:

Инициализация сокетных интерфейсов Win32API.

Инициализация сокета, т.е. создание специальной структуры данных и её инициализация вызовом функции.

«Привязка» созданного сокета к конкретной паре IP-адрес/Порт – с этого момента данный сокет (его имя) будет ассоциироваться с конкретным процессом, который «висит» по указанному адресу и порту.

Для серверной части приложения: запуск процедуры «прослушки» подключений на привязанный сокет.

Для клиентской части приложения: запуск процедуры подключения к серверному сокету (должны знать его IP-адрес/Порт).

Акцепт / Подтверждение подключения (обычно на стороне сервера).

Обмен данными между процессами через установленное сокетное соединение.

Закрытие сокетного соединения.

Итак, попытаемся реализовать последовательность Этапов, указанных выше, для организации простейшего чата между клиентом и сервером. Запускаем Visual Studio, выбираем создание консольного проекта на С++ и поехали.

Этап 0: Подключение всех необходимых библиотек Win32API для работы с сокетами

Сокеты не являются «стандартными» инструментами разработки, поэтому для их активизации необходимо подключить ряд библиотек через заголовочные файлы, а именно:

WinSock2.h – заголовочный файл, содержащий актуальные реализации функций для работы с сокетами.

WS2tcpip.h – заголовочный файл, который содержит различные программные интерфейсы, связанные с работой протокола TCP/IP (переводы различных данных в формат, понимаемый протоколом и т.д.).

Также нам потребуется прилинковать к приложению динамическую библиотеку ядра ОС: ws2_32.dll. Делаем это через директиву компилятору: #pragma comment(lib, “ws2_32.lib”)

Ну и в конце Этапа 0 подключаем стандартные заголовочные файлы iostream и stdio.h

Итого по завершению Этапа 0 в Серверной и Клиентской частях приложения имеем:

Обратите внимание: имя системной библиотеки ws2_32.lib именно такое, как это указано выше. В Сети есть различные варианты написания имени данной библиотеки, что, возможно, связано иным написанием в более ранних версиях ОС Windows. Если вы используете Windows 10, то данная библиотека называется именно ws2_32.lib и находится в стандартной папке ОС: C:/Windows/System32 (проверьте наличие библиотеки у себя, заменив расширение с “lib” на “dll”).

Этап 1: Инициализация сокетных интерфейсов Win32API

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

Нужно определить с какой версией сокетов мы работаем (какую версию понимает наша ОС) и

Запустить программный интерфейс сокетов в Win32API. Ну либо расстроить пользователя тем, что ему не удастся поработать с сокетами до обновления системных библиотек

Итого код Этапа 1 следующий:

Да, кода мало, а описания много. Так обычно и бывает, когда хочешь глубоко в чем-то разобраться. Так что на лабе будешь в первых рядах.

Этап 2: Создание сокета и его инициализация

Тип сокета: обычно задается тип транспортного протокола TCP ( SOCK_STREAM ) или UDP ( SOCK_DGRAM ). Но бывают и так называемые «сырые» сокеты, функционал которых сам программист определяет в процессе использования. Тип обозначается SOCK_RAW

Тип протокола: необязательный параметр, если тип сокета указан как TCP или UDP – можно передать значение 0. Тут более детально останавливаться не будем, т.к. в 95% случаев используются типы сокетов TCP/UDP.

При необходимости подробно почитать про функцию socket() можно здесь.

Код Этапа 2 будет выглядеть так:

Этап 3: Привязка сокета к паре IP-адрес/Порт

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

В ней уже более понятные пользователю поля, а именно:

Технический массив на 8 байт ( sin_zero[8] )

Соответственно, ввод данных для структуры типа sockaddr_in выглядит следующим образом:

Создание структуры типа sockaddr_in : sockaddr_in servInfo;

Заполнение полей созданной структуры servInfo

В случае ошибки функция возвращает значение меньше 0.

Соответственно, если мы хотим привязать сокет к локальному серверу, то наш код по преобразованию IPv4 адреса будет выглядеть так:

erStat = inet_pton(AF_INET, “127.0.0.1”, &ip_to_num);

Результат перевода IP-адреса содержится в структуре ip_to_num. И далее мы передаем уже в нашу переменную типа sockaddr_in значение преобразованного адреса:

Этап 4 (для сервера): «Прослушивание» привязанного порта для идентификации подключений

После вызова данной функции исполнение программы приостанавливается до тех пор, пока не будет соединения с Клиентом, либо пока не будет возвращена ошибка прослушивания порта. Код Этапа 4 для Сервера:

Этап 4 (для Клиента). Организация подключения к серверу

Функция возвращает 0 в случае успешного подключения и код ошибки в ином случае.

Этап 5 (только для Сервера). Подтверждение подключения

Всё, соединение между Клиентом и Сервером установлено! Самое время попробовать передать информацию от Клиента к Серверу и обратно. Как мы в начале и договорились, мы будет реализовывать простейший чат между ними.

Этап 6: Передача данных между Клиентом и Сервером

Рассмотрим прототипы функций recv() и send() :

Флаги в большинстве случаев игнорируются – передается значение 0.

Функции возвращают количество переданных/полученных по факту байт.

Как видно из прототипов, по своей структуре и параметрам эти функции совершенно одинаковые. Что важно знать:

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

предельно внимательно надо относиться к параметру «размер буфера». Он должен в точности равняться реальному количеству передаваемых байт. Если он будет отличаться, то есть риск потери части информации или «замусориванию» отправляемой порции данных, что ведет к автоматической поломке данных в процессе отправки/приёма. И совсем замечательно будет, если размер буфера по итогу работы функции равен возвращаемому значению функции – размеру принятых/отправленных байт.

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

Процесс непрерывного перехода от send() к recv() и обратно реализуется через бесконечный цикл, из которого совершается выход по вводу особой комбинации клавиш. Пример блока кода для Серверной части:

Пришло время показать итоговый рабочий код для Сервера и Клиента. Чтобы не загромождать и так большой текст дополнительным кодом, даю ссылки на код на GitHub:

Несколько важных финальных замечаний:

В итоговом коде я не использую проверку на точное получение отосланной информации, т.к. при единичной (не циклической) отсылке небольшого пакета информации накладные расходы на проверку его получения и отправку ответа будут выше, чем выгоды от такой проверки. Иными словами – такие пакеты теряются редко, а проверять их целостность и факт доставки очень долго.

При тестировании примера также видно, что чат рабочий, но очень уж несовершенный. Наиболее проблемное место – невозможность отправить сообщение пока другая сторона не ответила на твоё предыдущее сообщение. Суть проблемы в том, что после отсылки сообщения сторона-отправитель вызывает функцию recv(), которая, как я писал выше, блокирует исполнение последующего кода, в том числе блокирует вызов прерываний для осуществления ввода. Это приводит к тому, что набирать сообщение и что-то отправлять невозможно до тех пор, пока процесс не получит ответ от другой стороны, и вызов функции recv() не будет завершен. Благо введенная информация с клавиатуры не будет потеряна, а, накапливаясь в системном буфере ввода/вывода, будет выведена на экран как только блокировка со стороны recv() будет снята. Таким образом, мы реализовали так называемый прямой полудуплексный канал связи. Сделать его полностью дуплексным в голой сокетной архитектуре достаточно нетривиальная задача, частично решаемая за счет создания нескольких параллельно работающих потоков или нитей (threads) исполнения. Один поток будет принимать информацию, а второй – отправлять.

В последующих статьях я покажу реализацию полноценного чата между двумя сторонами (поможет разобраться в понятии «нити процесса»), а также покажу полноценную реализацию прикладного протокола по копированию файлов с Сервера на Клиент.

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *