что такое сокет в программировании

Сокеты¶

Сокеты (англ. 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 весь пакет = целое сообщение).

Источник

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

Jul 2, 2020 · 4 min read

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Источник

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Источник

Русские Блоги

Понимание сокета

Связь между сокетом и протоколом tcp / ip

1. Основная концепция сокета

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

2. Этапы сокетного соединения

Процесс соединения между сокетами можно разделить на 3 этапа:

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

Запрос клиента ‘
Сокет клиента отправляет запрос на подключение, а целью для подключения является сокет на стороне сервера. Для этого сокет клиента должен сначала описать сокет сервера, к которому он подключен, указать адрес и номер порта сокета на сервере, а затем сделать запрос на подключение к сокету на сервере.

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

3. Часто используемые функции

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

3.1、 socket()

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

Функциональный прототип:
int socket(int domain,int type,int protocol);

домен: домен протокола, также известный как семейство протоколов.
1) Обычно используются семейства протоколов: AF_INET, AF_INET6, AF_LOCAL (или AF_UNIX, сокет домена Unix), AF_ROUTE и т. д.

2) Семейство протоколов определяет тип адреса сокета, и соответствующий адрес должен использоваться при обмене данными. Например, AF_INET решает использовать комбинацию адреса ipv4 (32-разрядный) и номера порта (16-разрядный), AF_UNIX решает использовать Абсолютный путь используется как адрес.

3) Используется для определения, какой режим связи.

тип: указывает тип сокета.
1) Обычно используются следующие типы сокетов: SOCK_STREAM, SOCK_DGRAM, SOCK_RAW, SOCK_PACKET, SOCK_SEQPACKET и т. д.

протокол: указывает протокол.
1) Обычными протоколами являются IPPROTO_TCP, IPPROTO_UDP, IPPROTO_STCP, IPPROTO_TIPC и т. д.

Дескриптор сокета является целочисленным значением. В пространстве процессов каждого процесса имеется таблица дескрипторов сокетов, в которой хранится соответствие между дескрипторами сокетов и структурами данных сокетов. В этой таблице есть поле для хранения дескриптора вновь созданного сокета и другое поле для хранения адреса структуры данных сокета, чтобы вы могли найти соответствующую структуру данных сокета в соответствии с дескриптором сокета. Каждый процесс имеет таблицу дескрипторов сокетов в своем собственном пространстве процессов, но структура данных сокетов находится в буфере ядра операционной системы.
Когда мы вызываем socket для создания сокета, возвращаемый дескриптор сокета существует в пространстве семейства адресов (AF_XXX), но конкретного адреса нет. Если вы хотите назначить ему адрес, вы должны вызвать функцию bind (), в противном случае система автоматически назначит порт случайным образом при вызове connect () и listen ().

3.2, обязательный

Функция bind () назначает сокету определенный адрес в семействе адресов. Например, AF_INET и AF_INET6 соответствуют назначению комбинации адреса и номера порта IPV4 или IPV6 для сокета.

Возвращаемое значение:
success: return 0
не удалось: SOCKET_ERROR возвращается.

Обычно, когда сервер запускается, он связывает общеизвестный адрес (например, IP-адрес + номер порта) для предоставления услуг, и клиенты могут использовать его для подключения к серверу; клиенту не нужно указывать, а система автоматически назначает номер порта И свой собственный IP-адрес. Вот почему обычно серверная сторона будет вызывать bind () перед прослушиванием, но клиент не будет вызывать его, а система будет случайным образом генерировать его при connect ().

Порядок байтов в сети и хост

Порядок байтов хоста Обычно мы говорим, что это старшие и младшие порядковые порядки: разные процессоры имеют разные типы порядка байтов. Этот порядок байтов относится к порядку, в котором целые числа хранятся в памяти. Это называется порядком хоста. Определения эталонных стандартов Big-Endian и Little-Endian следующие:
a) Little-Endian означает, что младший байт расположен на младшем конце памяти, а старший старший байт расположен на старшем адресе памяти.
b) старший-байтовый означает, что старший байт расположен на младшем конце памяти, а младший байт расположен на старшем адресе памяти.
Сетевой порядок байтов : 32-битное значение 4 байта передается в следующем порядке: сначала 0

23 бит и, наконец, 24

Итак: при привязке адреса к сокету, пожалуйста, сначала преобразуйте порядок байтов хоста в порядок байтов сети и не предполагайте, что порядок байтов хоста использует Big-Endian в качестве порядка байтов сети.

3.3, прослушать () и подключиться ()

Если в качестве сервера, listen () будет вызван после того, как socket () и bind () будут вызваны для мониторинга сокета.Если клиент вызывает connect () для выдачи запроса на соединение в это время, сервер получит запрос.

listen()
Чтобы принять соединение, сначала используйте socket (), чтобы создать дескриптор сокета, затем используйте listen (), чтобы создать сокет и создать резервную копию журнала для соединения, к которому хотите применить, а затем используйте accept. () Принять соединение. Функция listen () применяется только к сокетам, поддерживающим соединения, например, тип SOCK_STREAM. Сокет s находится в режиме «изменения», и запрос соединения для приложения подтверждается и ставится в очередь для принятия. Эта функция особенно подходит для серверов, которые имеют несколько запросов на подключение одновременно: если очередь заполнена, когда приходит запрос на подключение, клиент получит ошибку WSAECONNREFUSED.

Сокет, созданный функцией socket (), по умолчанию является активным типом, а функция прослушивания изменяет сокет на пассивный тип, ожидая запроса соединения клиента.

connect()
Эта функция используется для создания соединения с указанным внешним портом. Параметр s указывает неподключенную дейтаграмму или потоковый сокет. Если сокет не связан, система назначает уникальное значение локальной ассоциации и устанавливает сокет как связанный. Обратите внимание, что если в поле адреса в структуре имени все нули, connect () вернет ошибку WSAEADDRNOTAVAIL.

Потоковые сокеты (тип SOCK_STREAM), используйте имя для установления соединения с удаленным хостом, как только вызов сокета успешно завершится, он может отправлять и получать данные. Для сокета типа дейтаграммы (тип SOCK_DGRAM) для него задан адрес назначения по умолчанию, и он используется для последующих вызовов send () и recv ().

Возвращаемое значение
Если ошибки не возникает, connect () возвращает 0.
В противном случае возвращается ошибка SOCKET_ERROR,

Приложение может получить соответствующий код ошибки через WSAGetLastError (). Для неблокирующих сокетов, если возвращаемое значение равно SOCKET_ERROR, приложение вызывает WSAGetLastError (). Если это означает, что код ошибки WSAEWOULDBLOCK, то ваше приложение может:
1. Используйте select (), чтобы определить, завершен ли запрос соединения, проверив, доступен ли сокет для записи.
2. Если ваше приложение использует WSAAsyncSelect () на основе сообщений для выражения интереса к событиям подключения, вы получите сообщение FD_CONNECT, когда операция подключения будет завершена.

Клиент устанавливает соединение с TCP-сервером, вызывая функцию соединения.

3.4, принять () функцию

После того как TCP-сервер последовательно вызовет socket (), bind () и listen (), он будет прослушивать указанный адрес сокета. После того, как клиент TCP вызывает socket () и connect () в этом порядке, он отправляет запрос на соединение на сервер TCP. После прослушивания этого запроса TCP-сервер вызовет функцию accept (), чтобы получить полученный запрос, чтобы установить соединение. После этого вы можете начать операции сетевого ввода-вывода, которые аналогичны операциям чтения и записи операций ввода-вывода для обычных файлов.

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

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

3.5 функции, такие как read () и write ()

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

read()/write()

recv()/send()

readv()/writev()

recvmsg()/sendmsg()

recvfrom()/sendto()

recvmsg () / sendmsg (): эти две функции являются наиболее распространенными функциями ввода / вывода. Фактически, вы можете заменить другие функции выше этими двумя функциями.

1. read()/write()

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

2. recv()/send()

Версия для Windows:

Здесь описывается только поток выполнения функции recv синхронного сокета. Когда приложение вызывает функцию recv:
(1) Recv сначала ожидает передачи данных в буфере отправки s по протоколу.Если протокол имеет ошибку сети при передаче данных в буфере отправки s, функция recv возвращает SOCKET_ERROR;

Функция recv возвращает фактическое количество скопированных байтов. Если recv делает ошибку во время копирования, он возвращает SOCKET_ERROR, если функция recv прерывается во время ожидания получения данных протоколом, то он возвращает 0.

Примечание: В системах Unix, если функция recv отключена во время ожидания получения данных протоколом, процесс, который вызывает recv, получит сигнал SIGPIPE.

send () применяется к подключенным пакетам данных или потоковым сокетам для отправки данных. Для сокетов дейтаграмм следует отметить, что длина отправляемых данных не должна превышать максимальную длину IP-пакетов в подсети связи. Максимальная длина IP-пакета указана в элементе iMaxUdpDg WSAData, возвращаемом вызовом WSAStartup (). Если данные слишком длинные для автоматической передачи протокола нижнего уровня, возвращается ошибка WSAEMSGSIZE, и данные не будут отправлены.

Обратите внимание, что успешное завершение вызова send () не означает, что передача данных наступила.

Если буферного пространства системы передачи недостаточно для сохранения передаваемых данных, если только сокет не находится в неблокирующем режиме ввода / вывода, send () заблокирует. Для неблокирующих сокетов типа SOCK_STREAM фактическое количество записанных данных может быть между 1 и требуемым размером, и его значение зависит от размера буфера локального и удаленного хостов. Вызов select () может использоваться для определения того, когда могут быть отправлены дополнительные данные.

3. readv()/writev()

UNIX и WINSOCK предоставляют разные методы реализации.В системе UNIX, используя writev, вы можете указать серию буферов, собрать данные для записи, чтобы вы могли расположить данные для сохранения в нескольких буферах, а затем записать их одновременно, чтобы избежать возникновения Взаимодействие между Nagle и алгоритмом отложенного ACK.

Функция: writev хранит несколько данных вместе и записывает данные, которые находятся в двух или более несвязанных буферах одновременно.

Описание параметра:
fd: дескриптор файла
iov: это набор указателей на структуру iovec. Структура iovec выглядит следующим образом:

Примечание: это определение взято из системы FreeBSD. Многие системы теперь определяют базовый указатель адреса как void * iov_base;

Эти две функции могут использоваться для сокетов и файловых дескрипторов любого типа.

4. recvmsg()/sendmsg()

Эти две функции являются наиболее распространенными функциями ввода / вывода. Фактически мы можем заменить все вызовы read, readv, recv и recvfrom на вызовы recvmsg. Аналогично, различные вызовы функций вывода также могут быть заменены вызовами sendmsg.

5. recvfrom()/sendto()

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

3.6, функция close ()

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

4. Как сообщить другой стороне, что команда была отправлена

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

Но у этого метода есть некоторые недостатки

Как закрыть выходной поток через сокет

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

Если согласован односторонний конец, это означает, что отправка завершена. Например, следующее сообщение end означает, что отправка сообщения завершена:
what is your name?
end

В настоящее время метод чтения сервера необходимо изменить:

Можно видеть, что сервер не только оценивает, читается ли конец потока, но также оценивает, читается ли конец соглашения.

Преимущества и недостатки заключаются в следующем:

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

Распаковка и наклеивание

При использовании связи через сокет я более или менее слышал о распаковке и липкой упаковке. Если я не слышал об этом и запрограммировал ненадлежащим образом, я иногда сталкиваюсь с некоторыми необъяснимыми проблемами. Все эти знания все еще важны, по крайней мере Знать, как это произошло и как это предотвратить.
Теперь кратко объясним причины распаковки и залипания:

Прежде всего, понятно, что в большинстве случаев мы не хотим распаковывать и залипать (если хотите, можете делать все), так как этого избежать, подробно объяснено ниже?

Липкая сумка
Прежде всего, мы должны правильно обрабатывать липкие пакеты. Липкие пакеты на самом деле являются оптимизацией сетевого взаимодействия. Если верхний уровень отправляет только один байт данных, нижний уровень отправляет 41 байт. Среди них 20 байтов IP-заголовка, 20 байтов TCP-заголовка и 1 байт данных, и вам необходимо подтвердить после отправки, что приводит к потере пропускной способности и вызывает перегрузку сети при большом количестве. Конечно, у него все еще есть некоторые недостатки, потому что он объединит некоторые пакеты, что приведет к тому, что данные не будут отправлены немедленно, что приведет к задержке. Если это приемлемо (обычно задержка составляет 200 мс), то не рекомендуется отключать эту оптимизацию. Пакеты могут привести к бизнес-ошибкам, поэтому, пожалуйста, исправьте алгоритм (протокол) чтения вашего сервера, потому что, даже если липкие пакеты не возникают, кэш сервера может быть объединен и отправлен на верхний уровень. Рекомендуется использовать length + type + Режим данных.
Если вам не нужны залипшие пакеты, вы можете отключить TCP_NODELAY, и в Socket есть соответствующие методы:
void setTcpNoDelay(boolean on)
можно установить в значение true, чтобы предотвратить залипание пакетов при отправке, но когда скорость отправки превышает скорость чтения, на сервере также будут происходить залипание пакетов, то есть сервер читает Выборка слишком медленная, из-за чего она читает несколько пакетов одновременно.

Распаковка
Максимальная длина сегмента (MSS) указывает длину самого большого блока данных, передаваемых из TCP на другой конец. Когда соединение установлено, обе стороны соединения должны объявить свой MSS. Клиент будет пытаться удовлетворить требования сервера и не может быть больше значения MSS сервера. Когда нет согласования, будет использоваться значение 536 байт. Хотя кажется, что чем больше значение MSS, тем лучше, но, учитывая некоторые другие обстоятельства, это значение все еще не легко определить.
Как справиться с распаковкой, то есть как указать, что сообщение отправлено. Для шаблона с известной длиной данных вы можете создать массив одинакового размера и прочитать его в цикле. Пример кода следующий:

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

Источник

Понравилась статья? Поделиться с друзьями:

Не пропустите наши новые статьи:

  • Что такое сои в программировании
  • Что такое содержание учебного предмета в рабочей программе
  • Что такое содержание программы дополнительного образования
  • что такое совместимость программного обеспечения
  • Что такое совместимость программ

  • Операционные системы и программное обеспечение
    0 0 голоса
    Рейтинг статьи
    Подписаться
    Уведомить о
    guest
    0 комментариев
    Старые
    Новые Популярные
    Межтекстовые Отзывы
    Посмотреть все комментарии