сокет tcp что это

Сокеты¶

Сокеты (англ. socket — разъём) — название программного интерфейса для обеспечения обмена данными между процессами. Процессы при таком обмене могут исполняться как на одной ЭВМ, так и на различных ЭВМ, связанных между собой сетью. Сокет — абстрактный объект, представляющий конечную точку соединения.

Принципы сокетов¶

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

Каждый сокет имеет свой адрес. ОС семейства UNIX могут поддерживать много типов адресов, но обязательными являются INET-адрес и UNIX-адрес. Если привязать сокет к UNIX-адресу, то будет создан специальный файл (файл сокета) по заданному пути, через который смогут сообщаться любые локальные процессы путём чтения/записи из него (см. Доменный сокет Unix). Сокеты типа INET доступны из сети и требуют выделения номера порта.

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

Основные функции¶

Общие
SocketСоздать новый сокет и вернуть файловый дескриптор
SendОтправить данные по сети
ReceiveПолучить данные из сети
CloseЗакрыть соединение
Серверные
BindСвязать сокет с IP-адресом и портом
ListenОбъявить о желании принимать соединения. Слушает порт и ждет когда будет установлено соединение
AcceptПринять запрос на установку соединения
Клиентские
ConnectУстановить соединение

socket()¶

Создаёт конечную точку соединения и возвращает файловый дескриптор. Принимает три аргумента:

domain указывающий семейство протоколов создаваемого сокета

type

protocol

Протоколы обозначаются символьными константами с префиксом IPPROTO_* (например, IPPROTO_TCP или IPPROTO_UDP). Допускается значение protocol=0 (протокол не указан), в этом случае используется значение по умолчанию для данного вида соединений.

Функция возвращает −1 в случае ошибки. Иначе, она возвращает целое число, представляющее присвоенный дескриптор.

Связывает сокет с конкретным адресом. Когда сокет создается при помощи socket(), он ассоциируется с некоторым семейством адресов, но не с конкретным адресом. До того как сокет сможет принять входящие соединения, он должен быть связан с адресом. bind() принимает три аргумента:

Возвращает 0 при успехе и −1 при возникновении ошибки.

Автоматическое получение имени хоста.

listen()¶

Подготавливает привязываемый сокет к принятию входящих соединений. Данная функция применима только к типам сокетов SOCK_STREAM и SOCK_SEQPACKET. Принимает два аргумента:

После принятия соединения оно выводится из очереди. В случае успеха возвращается 0, в случае возникновения ошибки возвращается −1.

accept()¶

Используется для принятия запроса на установление соединения от удаленного хоста. Принимает следующие аргументы:

Функция возвращает дескриптор сокета, связанный с принятым соединением, или −1 в случае возникновения ошибки.

connect()¶

Устанавливает соединение с сервером.

Некоторые типы сокетов работают без установления соединения, это в основном касается UDP-сокетов. Для них соединение приобретает особое значение: цель по умолчанию для посылки и получения данных присваивается переданному адресу, позволяя использовать такие функции как send() и recv() на сокетах без установления соединения.

Загруженный сервер может отвергнуть попытку соединения, поэтому в некоторых видах программ необходимо предусмотреть повторные попытки соединения.

Возвращает целое число, представляющее код ошибки: 0 означает успешное выполнение, а −1 свидетельствует об ошибке.

Передача данных¶

Для передачи данных можно пользоваться стандартными функциями чтения/записи файлов read и write, но есть специальные функции для передачи данных через сокеты:

Нужно обратить внимание, что при использовании протокола TCP (сокеты типа SOCK_STREAM) есть вероятность получить меньше данных, чем было передано, так как ещё не все данные были переданы, поэтому нужно либо дождаться, когда функция recv возвратит 0 байт, либо выставить флаг MSG_WAITALL для функции recv, что заставит её дождаться окончания передачи. Для остальных типов сокетов флаг MSG_WAITALL ничего не меняет (например, в UDP весь пакет = целое сообщение).

Источник

Сокеты

Сокеты объединили в едином интерфейсе потоковую передачу данных подобную каналам pipe и FIFO и передачу сообщений, подобную очередям сообщений в System V IPC. Кроме того, сокеты добавили возможность создания клиент-серверного взаимодействия (один со многими).

Классификация сокетов

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

Передача записей ограниченной длины. Записи на уровне интерфейса сокетов никак не связанны между собой. Отправка записей описывается фразой: «отправил и забыл». Принимающий процесс получает записи по отдельности в непредсказуемом порядке или не получает вовсе.

Надёжная упорядоченная передача с делением на записи. Использовался в Sequence Packet Protocol для Xerox Network Systems. Не реализован в TCP/IP, но может быть имитирован в TCP через Urgent Pointer.

Имена сокетов

Имена сокетов на сервере назначаются вызовом bind(), а на клиенте, как правило, генерируются ядром.

TCP/IP

Для передачи данных с помощью семействе протоколов TCP/IP реализованы два вида сокетов Stream и Datagram. Все остальные манипуляции с сетью TCP/IP осуществляются через Raw-сокеты.

API Сокетов

Создание сокета

protocol Поскольку в семействе протоколов TCP/IP протокол однозначно связан с типом сокета, а в домене Unix понятие протокола вообще отсутствует, то этот параметр всегда равен нулю, что соответствует автовыбору.

В домене Unix возможно создание пары соединённых между собой безымянных сокетов, которые буду вести себя подобно неименованному каналу pipe. В отличие от неименованных каналов, оба сокета открыты и на чтение и на запись.

Назначение имени

Для того, чтобы клиенты могли подключаться к серверу, сервер должен иметь заранее известное имя. Вызов bind() обеспечивает назначение имени серверному сокету. Сервер получит имя клиентского сокета в момент соединения (stream) или получения сообщения (datagram), поэтому на клиентской стороне имя сокету, как правило, назначается ядром ОС, хотя и явное присвоение с помощью bind() остаётся доступным.

Соединение с сервером (в основном Stream)

Для сокета типа Stream вызов connect() соединяет сокет клиента с сокетом сервера, создавая поток передачи данных. Адрес сервера servaddr заполняется по тем же правилам, что и адрес, передаваемый в bind().

Для сокета типа Datagram вызов connect() запоминает адрес получателя, для отправки сообщений вызовом send(). Можно пропустить этот вызов и отправлять сообщения вызовом sendto(), явно указывая адрес получателя для каждого сообщения.

Прослушивание сокетов сервером (только Stream)

Вызов listen() на стороне сервера превращает сокет в фабрику сокетов, которая будет с помощью вызова accept() возвращать новый транспортный сокет на каждый вызов connect() со стороны клиентов.

Обработка запроса клиента.

Клиентский connect() будет заблокирован до тех пор, пока сервер не вызовет accept(). accept() возвращает транспортный сокет, который связан с сокетом для которого клиент вызвал connect(). Этот сокет используется как файловый дескриптор для вызовов read(), write(), send() и recv().

В переменную clntaddr заносится адрес подключившегося клиента.

Чтение/запись данных

Для операций чтения-записи данных через сокеты могут применяться стандартные вызовы read() и write(), однако существуют и более специализированные вызовы:

Все вызовы применимы и к потоковым сокетам и к сокетам датаграмм. При попытке прочитать датаграмму в слишком маленький буфер, её хвост будет утерян.

write(fd,buf,size) == send(fd,buf,size,0) == sendto(fd,buf,size,0,NULL,0)

send() может применяться только к тем сокетам, для которых выполнен connect().

sendmsg() и recvmsg() близки к вызовам writev() и readv(), поскольку позволяют одним вызовом отправить/принять несколько буферов данных.

Управление окончанием соединения (в основном Stream)

Вызов close() закрывает сокет и освобождает все связанные с ним структуры данных.

Для контроля над закрытием потоковых сокетов используется вызов shutdown(), который позволяет управлять окончанием соединения.

int shutdown () (int sock, int cntl);

Аргумент cntl может принимать следующие значения:

Для реализации клиент-серверной архитектуры на основе сокетов необходимо предоставить разработчику сервера инструмент для параллельной работы с несколькими клиентами. Возможные варианты:

Последний вариант является наиболее часто используемым в Unix и реализуется вызовами select() и poll().

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

Реализация этих вызовов позволяет использовать их для отслеживания состояния любых файловых дескрипторов, а не только сокетов.

SELECT

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

Параметр nfds задает номер максимального выставленного флага и служит для оптимизации.

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

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

Таймаут задаётся структурой timeval, содержащей секунды и микросекунды

Поскольку вызов sleep() работает с точностью до секунды, то для приостановки процесса на более короткие промежутки времени часто используют select() с указателями NULL вместо указателей на флаги.

Вызов poll() функционально эквивалентен select. Его параметры как бы «вывернуты наизнанку» по сравнению с select(). Вместо трёх наборов битовых файлов в poll() массив интересующих файловых дескрипторов размером nfds. С каждым файловым дескриптором связаны две переменные: флаги интересующих событий и флаги случившихся событий. Время таймаута задаётся в миллисекундах.

struct pollfd < int fd; /* file descriptor / short events; / requested events / short revents; / returned events */ >;

Битовые флаги в events определяются макросами:

Диаграмма взаимодействия сокетов datagram

Ниже представлена временная диаграмма соединения клиента и сервера через сокет типа Datagram

СерверКлиент
Создание сокета socket()Создание сокета socket()
Присвоение имени bind()
Начало цикла работы с клиентами
Прием сообщения с адресом отправителя recvfrom()Приём сообщения recv()
Закрытие сокета close()
Конец цикла работы с клиентами
Закрытие сокета close()

Диаграмма взаимодействия сокетов stream

Ниже представлена временная диаграмма соединения клиента и сервера через сокет типа Stream

Источник

Сокеты

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

В этом разделе основное внимание уделяется использованию классов сокетов универсальной платформы Windows (UWP), которые находятся в пространстве имен Windows.Networking.Sockets. Кроме того, сокеты Windows 2 (WinSock) можно использовать в приложении UWP.

Как последствие сетевой изоляции WIndows запрещает установку подключения сокета (Sockets или WinSock) между двумя приложениями UWP, работающими на одном компьютере, через локальный петлевой адрес (127.0.0.0) либо путем явного указания локального IP-адреса. Дополнительные сведения о механизмах, с помощью которых приложения UWP могут взаимодействовать друг с другом, см. в разделе Связь между приложениями.

Создание базового клиента и сервера сокета TCP

Для постоянных подключений сокет протокола TCP обеспечивает в сети низкоуровневую двунаправленную передачу данных. Сокеты TCP широко используются большинством сетевых протоколов в Интернете. Чтобы продемонстрировать базовые операции TCP, в следующем примере кода реализованы отправка и получение данных через TCP объектами StreamSocket и StreamSocketListener, на основе которых создаются эхо-клиент и сервер.

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

Эхо-клиент и сервер на основе сокетов TCP

Создайте StreamSocketListener и начните слушать входящие подключения TCP. Событие StreamSocketListener.ConnectionReceived создается всякий раз, когда клиент устанавливает подключение к прослушивателю StreamSocketListener.

Кроме того, создайте сокет StreamSocket, установите подключение к серверу, отправьте запрос и получите ответ.

Ссылки на StreamSockets в продолжениях C++ PPL (в первую очередь применимо к C++/CX)

Это неприменимо в случае использования сопрограмм C++/WinRT и передачи параметров по значению. Рекомендации по передаче параметров см. в разделе Параллельная обработка и асинхронные операции с помощью C++/WinRT.

StreamSocket остается активным, пока в его потоке ввода/вывода выполняются активные операции чтения/записи (рассмотрим для примера StreamSocketListenerConnectionReceivedEventArgs.Socket, доступ к которому осуществляется в обработчике событий StreamSocketListener.ConnectionReceived). При вызове DataReader.LoadAsync (или ) он хранит ссылку на сокет (через поток ввода сокета) до тех пор, пока обработчик событий Completed (при наличии) метода LoadAsync не завершит выполнение.

Библиотека параллельных шаблонов (PPL) не планирует встроенное продолжение задач по умолчанию. Другими словами, добавление задачи продолжения (с task::then() ) не гарантирует, что задача продолжения будет выполняться во встроенном режиме в качестве завершающего обработчика.

С точки зрения StreamSocket завершающий обработчик завершит выполнение (и сокет станет готовым к ликвидации) до запуска основной части продолжения. Таким образом, чтобы предотвратить удаление сокета, если вы хотите использовать его в этом продолжении, необходимо ссылаться на сокет напрямую (через захват лямбда-функции) и использовать его, или косвенно (продолжая осуществлять доступ к args->Socket внутри продолжения), или обеспечить принудительное выполнение задач продолжения в коде. Эту первую технику можно наблюдать в действии (захват лямбда-функции) в примере StreamSocket. Код C++/CX в разделе Создание базового клиента и сервера сокета TCP выше использует второй способ. Он возвращает запрос в качестве ответа и осуществляет доступ к из одного из продолжений самого глубокого уровня.

Третий способ подходит в тех случаях, когда не нужно выводить ответ. Параметр task_continuation_context::use_synchronous_execution() используется для принудительного выполнения основной части продолжения внутри PPL. Этот пример кода демонстрирует, как это сделать.

Это поведение применяется ко всем сокетам и классам WebSockets в пространстве имен Windows.Networking.Sockets. Но для сценариев на стороне клиента сокеты обычно сохраняются в переменных-членах, так что эта проблема наиболее применима для сценария StreamSocketListener.ConnectionReceived, как описано выше.

Создание простейших клиента и сервера для UDP-сокетов

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

Чтобы продемонстрировать базовые операции UDP, пример кода ниже показывает класс DatagramSocket, который используется для отправки и получения данных через UDP с целью формирования эхо-клиента и сервера. Создайте новый проект и поместите представленный ниже код клиента и сервера в один проект. Как и в случае с сокетом TCP, необходимо объявить возможность приложения Частные сети (клиент сервер).

Создание эхо-клиента и эко-сервера с использованием сокетов UDP

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

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

Фоновые операции и брокер сокета

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

Пакетные отправки

Каждый раз, когда вы выполняется запись в поток, связанный с сокетом, происходит переход из режима пользователя (обычный код) в режим ядра (где работает сетевой стек). Если записывается много буферов одновременно, повторяющиеся переходы создают значительную нагрузку. Чтобы отправлять несколько буферов данных одновременно, избегая такой нагрузки, можно собирать отправляемые данные в пакеты. Это особенно полезно, если ваше приложение поддерживает VoIP, VPN или другие задачи, предполагающие максимально эффективное перемещение больших объемов данных.

В этом разделе показано несколько техник пакетных отправок, которые можно использовать с сокетом StreamSocket или подключенным сокетом DatagramSocket.

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

Следующий пример подходит для любого языка UWP, а не только для C#. В его основе — поведение потоков StreamSocket.OutputStream и DatagramSocket.OutputStream, объединяющих отправки. Эта техника вызывает метод FlushAsync в потоке вывода, который начиная с Windows 10 гарантированно возвращается только после того, как все операции потока вывода завершены.

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

Совместное использование порта для DatagramSocket

Предоставление сертификата клиента с классом StreamSocket

Класс StreamSocket поддерживает возможность использования протокола SSL/TLS для проверки подлинности сервера, к которому обращается клиентское приложение. В некоторых случаях клиентское приложение также должно пройти проверку подлинности на сервере с помощью сертификата клиента SSL/TLS. Можно предоставить клиентский сертификат со свойством StreamSocketControl.ClientCertificate, прежде чем привязывать или подключать сокет (его необходимо задать до начала подтверждения протокола SSL/TLS). Доступ к экземпляру StreamSocketControl осуществляется из объекта StreamSocket через свойство StreamSocket.Control. Если сервер запрашивает сертификат клиента, Windows ответит, воспользовавшись предоставленным клиентским сертификатом.

Используйте переопределение метода StreamSocket.ConnectAsync, которое принимает значение SocketProtectionLevel, как показано в примере минимального кода.

Как указано в комментарии в примерах кода ниже, чтобы код работал, в проекте должна быть объявлена возможность приложения sharedUserCertificates.

Обработка исключений

Ошибка, обнаруженная в операции DatagramSocket, StreamSocket или StreamSocketListener, возвращается в виде значения HRESULT. Можно передать значение HRESULT методу SocketError.GetStatus, чтобы преобразовать его в значение перечисления SocketErrorStatus.

Большинство значений перечисления SocketErrorStatus соответствуют ошибке, возвращаемой стандартной операцией с сокетами Windows. Ваше приложение может включать значения перечисления SocketErrorStatus, чтобы по-разному действовать в зависимости от причины исключения.

Конструктор HostName может создать исключение, если переданная строка не является допустимым именем узла. Например, он содержит недопустимые символы, что вероятно, если имя узла вводится в приложении пользователем. Создайте HostName внутри блока try/catch. В этом случае приложение может сообщить пользователю об ошибке и запросить новое имя узла.

Источник

Основы программирования TCP-сокетов на Java

сокет tcp что это. Смотреть фото сокет tcp что это. Смотреть картинку сокет tcp что это. Картинка про сокет tcp что это. Фото сокет tcp что это

Клиент-серверная архитектура — наиболее распространенная структура приложений в Интернете. В этой архитектуре клиенты (т.е. персональные компьютеры, устройства Интернета вещей и т. д.) сначала запрашивают ресурсы с сервера. Затем сервер отправляет обратно соответствующие ответы на запросы клиентов. Чтобы это произошло, должен быть какой-то механизм, реализованный как на стороне клиента, так и на стороне сервера, который поддерживает эту сетевую транзакцию. Этот механизм называется коммуникацией посредством сокетов.

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

В этой статье мы более подробно рассмотрим сокеты и простую клиент-серверную реализацию с использованием сокетов в Java.

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

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

Сокет — это программная (логическая) конечная точка, устанавливающая двунаправленную коммуникацию между сервером и одной или несколькими клиентскими программами. Сокет — это нечто “программное”. Другими словами, сокет не существует на физическом уровне. Прикладное программное обеспечение определяет сокет так, чтобы он использовал порты на основном компьютере для его реализации. Это позволяет программистам комфортно работать с низкоуровневыми деталями сетевых коммуникаций, такими как порты, маршрутизация и т. д., внутри прикладного кода.

Как работают сокеты?

TCP-сокет устанавливает связь между клиентом и сервером в несколько этапов.

На каждой из перечисленных выше стадий коммуникации сокетов “под капотом» происходит много всего сложного. Однако этих знаний вполне достаточно для понимания и демонстрации того, как работает коммуникация посредством TCP-сокетов.

К настоящему времени мы уже достаточно знаем о TCP-сокетах. Давайте теперь посмотрим на них в действии.

Реализация коммуникации посредством TCP-сокетов в Java

Давайте посмотрим, как мы можем реализовать коммуникацию сокетов в Java. Мы сейчас напишем две Java-программы. Одной будет программа, запущенная на сервере, а другой — клиентская программа, которая будет взаимодействовать с сервером.

Реализация серверного сокета

Теперь давайте создадим клиент для взаимодействия с серверным сокетом, созданным выше.

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

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

Запуск программ

Сначала запустите серверную Java-программу, а затем клиентскую Java-программу (потому что сервер уже должен работать для подключения клиента). Вы увидите Received data: Java Revisited в терминале, где работает клиентская программа. Вот что здесь произошло: серверная программа отправила данные клиенту по запросу, а клиентская программа вывела их на терминал.

В этой статье мы обсудили, что такое сокеты и Java-реализация связи TCP-сокетов.

Источник

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

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