nearby server socket что это

Android: Сетевые коммуникации с помощью Nearby (PlayServices API)

Совсем недавно Google предоставила мобильным разработчикам Android новую технологию сетевого обмена данными — Nearby. Мне она стала сразу интересна, так как позволяет устанавливать локальное соединение между Android устройствами без особых заморочек! Нет нужды заставлять пользователя вводить IP адрес и порт, он просто инициирует соединение, а клиенты к нему просто подключаются. На странице описывающей технологию указаны следующие варианты использования:
— многопользовательские игры на индивидуальных экранах – игроки играют в сетевые игры каждый со своего устройства, которые объединены в сеть (классика жанра);
— многопользовательские игры на общем экране – в данном случае в качестве сервера может выступать GoogleTV, на нём будет происходить основной игровой процесс, а все подключившиеся будут использовать свой телефон/планшет в качестве игрового контроллера (как на фото!);
— и конечно для любого обмена данными между различными Android устройствами.

nearby server socket что это. Смотреть фото nearby server socket что это. Смотреть картинку nearby server socket что это. Картинка про nearby server socket что это. Фото nearby server socket что это

Уже сейчас вы можете пропробовать эту технологию в игре Beach Buggy Racing:

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

Рассмотрим принципы работы с Nearby.
Дабы не создавать велосипед я взял оригинальный пример и рассмотрел его с переводом всех комментариев.
Прежде всего удостоверьтесь что на вашем телефоне имеется последняя версия сервисов GooglePlay — https://play.google.com/store/apps/details?id=com.google.android.gms.
Теперь перейдём к основным моментам проекта:
В проект добавлена библиотека PlayServices (в файл «build.gradle»), именно она позволяет работать с Nearby:

Работу с Nearby можно разделить на следующие этапы:
1) Создание главного объекта доступа – GoogleApiClient. Запуск клиента. Остановка клиента
2) Запуск рекламации намерения стать точкой доступа
3) Запуск поиска точек для соединения
4) Присоединение к точке
5) Обработка заявок на присоединение
6) Контроль соединения
7) Принятие и обработка сообщений от оппонента
8) Отправка сообщения
Рассмотрим всё по порядку.

Создание главного объекта доступа – GoogleApiClient. Запуск клиента. Остановка клиента. Тут всё просто. В конструкторе активности создаём главный объект доступа к Nearby. При старте активности запускаем его, при остановке активности отключаемся от сети.

Следующий этап — Запуск рекламации намерения стать точкой доступа, метод startAdvertising:

Если пользователь будет беспрестанно «жмахать» по кнопке “Advertise”, он получит сообщение что мол всё работает нормально, расслабся 🙂 — STATUS_ALREADY_ADVERTISING

Третий этап — Запуск поиска точек для соединения:

Всё очень прозрачно и понятно. Просто запуск поиска точек доступа.

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

В методе “connectTo” реализован диалог выбора точки к которой возможно подключиться. При выборе одного из варианта переходим к непосредственному подключению:

Если всё прошло успешно, то можно начинать обмен сообщениями.

Для обработки заявок на присоединение предназначен метод onConnectionRequest:

За контроль соединения отвечают ряд методов:
onDisconnected – обработка разрыва связи;
onConnected – обработка подключения;
onEndpointLost – обработка разрыва связи;
onConnectionSuspended – обработка прерывание соединения;
onConnectionFailed – обработка неудачного соединения.
Контроль за переподключением клиентов (например при разрыве связи при выходе пользователя из зоны действия WiFi) полностью ложится на разработчика.

Для обработки приходящих сообщений необходимо переписать метод onMessageReceived:

Отправка сообщений осуществляется с помощью двух методов:
1) Nearby.Connections.sendReliableMessage – отправка надёжных сообщений;
2) Nearby.Connections.sendUnreliableMessage – отправка ненадёжных сообщений.
При использовании первого метода, система сама контролирует правильность очерёдности доставляемых сообщений, во втором случае последовательность может нарушиться, так как контроля никакого нет. Зато второй метод быстрее, поэтому его лучше использовать когда требуется отправлять большое количество сообщений, например при отправке положения курсора на экране.

В ресурсах необходимо указать идентификатор сервиса по которому будет происходить поиск и подключения клиентов.

Для разрешения рекламации приложения в манифесте необходимо прописать следующее:

Если вы соберёте это приложение и запустите его на своих устройствах то сможете наблюдать следующее:

При первом взгляде может показаться что использование API Nearby сложно и громоздко, но это только на первый взгляд. В итоге разработчик получает готовый, надёжный, контролируемый инструмент для сетевого обмена данными. Лично мне это решение очень понравилось, не надо больше контролировать очередность прихода пакетов с данными, просить пользователей ввести ip адрес и номер сокета, производить дополнительные настройки… Красота!

Спасибо за помощь в подготовке материала inatale!

Источник

Nearby server socket что это

Сетевые сокеты — способ взаимодействия любого приложения с системой на которой оно работает. Сокет — это интерфейс, который по сути представляет собой совокупность адреса в сети и используемого порта. Также часто термин употребляется применительно к Socket API, о котором рассказывается во второй части статьи.

Клиентское приложение всегда работает на локальной машине, подключенной к сети

Интерфейс между приложением и хост-машиной (Network-Application Interface) определяет как приложение может использовать сеть.

nearby server socket что это. Смотреть фото nearby server socket что это. Смотреть картинку nearby server socket что это. Картинка про nearby server socket что это. Фото nearby server socket что это

Сетевые сокеты и клиент серверная модель

Приложение клиента (посылает например URL в случае с вебом или запрос к MySQL) на определенный сетевой адрес и порт. В примере это localhost и порт 3306 — сервер в свою отвечает приложению. К приложению при этом могут обращаться множество клиентов, запросы и использованием сокета приходят на один и тот же адрес и обрабатываются одним пакетом. Таким образом работает клиент-серверая модель взаимодействия.

Чтобы написать приложение, которое могло бы обслуживать множество клиентов (последовательно и параллельно) нужно сокет API

Socket API — интерфейс используемый всеми интернет приложениями.

Socket API при соединении 2-х приложений может работать с потоками и с датаграммами :

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

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

Вызовы в Socket API

nearby server socket что это. Смотреть фото nearby server socket что это. Смотреть картинку nearby server socket что это. Картинка про nearby server socket что это. Фото nearby server socket что это
SOCKET — вызов создает структуру

BIND — связывает локальный адрес с сокетом

LISTEN — заявляет о готовности установить соединение

ACCEPT — принимает входящее соединение

CONNECT — пробует установить соединение

SEND — отправляет данные в рамках соединения

RECEIVE — принимает информацию в рамках соединения

CLOSE — прерывает соединение

Источник

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

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

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

nearby server socket что это. Смотреть фото nearby server socket что это. Смотреть картинку nearby server socket что это. Картинка про nearby server socket что это. Фото nearby server socket что это

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()

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

nearby server socket что это. Смотреть фото nearby server socket что это. Смотреть картинку nearby server socket что это. Картинка про nearby server socket что это. Фото nearby server socket что это

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, тем лучше, но, учитывая некоторые другие обстоятельства, это значение все еще не легко определить.
Как справиться с распаковкой, то есть как указать, что сообщение отправлено. Для шаблона с известной длиной данных вы можете создать массив одинакового размера и прочитать его в цикле. Пример кода следующий:

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

Источник

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

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