Работа с сокетом во Flutter
В прошлой статье я рассказывал о том, как сделать простое приложение по мониторингу на flutter. Но для полноты картины я решил описать как отправлять полученные координаты на сервер. Для передачи данных я решил использовать protobuf.
Создание protobuf схемы.
Для того чтобы быть уверенными что данные в нашем приложении имеют строго определенный формат на нужна какая-то схема, при валидации которой сразу можно понять валидное сообщение или нет. Для текстовых форматов эта может быть XSD схема для XML или JSON схема для JSON. Однако передавать текстовые данные по сети накладно, из-за большого их объема. Тут на помощь и приходят бинарные форматы данных, такие как protobuf.
Для начала работы нужно составить схему данных в моем случае она будет следующая:
syntax = "proto3"; package test; message Packet
В этой схеме мы описываем версию протокола, имя пакета и структуру сообщений. В структуре сообщений мы задаем тип поля, его название и номер. После того схема составлена, её нужно сохранить.
Далее на основе этой схемы мы можем генерировать структру данных для различных языков (они описаны в руководстве).
В моем случае мне нужны 2 языка — Dart и Go. Первый используется в мобильном приложении, а на втором будет написан тестовый сервер. Для этого необходимо в папке со схемой выполнить:
protoc --go_out=. test.proto protoc --dart_out=. test.proto
После того как эти команады отработают в папке появится файл test.pb.go с описание Go структуры и 4 файла для мобильного приложения:
test.pb.dart test.pbenum.dart test.pbjson.dart test.pbserver.dart
Соответственно надо перенести в папки где находятся ваши приложения.
Тестовый сервер
Для проверки того, что приложение нам отправляет данные необходим простенький сервер. Я решил написать его на Go:
package main import ( "log" "net" "github.com/golang/protobuf/proto" "io" ) func main() < srvAddress := "localhost:5555" l, err := net.Listen("tcp", srvAddress) if err != nil < log.Fatalf("Не удалось открыть соединение: %v", err) >defer l.Close() log.Printf("Запущен сервер %s. ", srvAddress) for < conn, err := l.Accept() if err != nil < log.Printf("Ошибка соединения: %v", err) >else < go handleRecvPkg(conn) >> > func handleRecvPkg(conn net.Conn) < defer conn.Close() buf := make([]byte, 1024) log.Printf("Установлено соединение с %s", conn.RemoteAddr()) for < packetLen, err := conn.Read(buf) switch err < case nil: recvPacket := buf[:packetLen] log.Printf("Принят пакет: %X", buf[:packetLen]) outPkg := Packet<>if err := proto.Unmarshal(recvPacket, &outPkg); err != nil < log.Printf("Ошибка декодирования пакета: %v", err) return >log.Println("Данные в пакете: ", outPkg) case io.EOF: continue default: log.Printf("Ошибка при получении: %v", err) return > > >
Сервер открывает сокет на порту 5555 и на каждое соединение запускает горутину. Горутина в свою очередь считывает принятые данные и с помощью библиотеки proto разбирает данные в структуру Packet из файла test.pb.go, который была сгенерирован из схемы protobuf с помощью protoc.
Модификация мобильного приложения
Для работы с protobuf необходимо добавть соответствующий модуль в pubspec.yaml:
dependencies: protobuf: ^0.13.15
Далее в файле нашего приложения необходимо импортировать нужные модули:
import 'dart:io'; import 'package:mobileapp/test.pb.dart'; // сгенерированный protoc файл .
После этого в конец кода обработки геопозиции нужно добавить:
. location.getLocation().then((p) < . locPkg = Packet(); locPkg.client = 1; locPkg.longitude = p.latitude; locPkg.latitude = p.longitude; Socket.connect('localhost', 5555).then((s) < s.add(locPkg.writeToBuffer()); s.destroy(); >).catchError((e) < print(e.toString()); >); >); .
В этом куске кода мы создаем класс нашего пакета из protobuf схемы, а затем добавляем в него необходимые поля. Затем мы создаем tcp соединение с сервером и отправляем на него бинарный пакет, который создает функция writeToBuffer , затем соедиение закрывается.
В итоге после запуска приложения в логах отладочного сервиса можно увидеть следующее:
Заключение
В статье показан базовый уровень взаимодействия с сервером. Данный код каждый раз в момент отправки пакета создает новое соединение, что в боевоей системе не очень хорошо. Также если возникнет необходимость использовать UDP протокол для передачи данных, для уменшения издержек, то в место Socket , можно использовать RawDatagramSocket . Хороший пример по работе с UDP, можно посмотреть в статье.
Ссылки
- Protocol buffers developer guide
- Proto
- UDP Socket Programming with Dart
- How to set up Flutter platform channels with Protobuf
Как на архитектуре BLoC сделать вебсокет с локальной sqlite базой данных
Я реализую мессенджер. Через Bloc реализовал авторизацию пользователя, после авторизации мне необходимо создать сокет соединение и с разных виджетов UI передавать запросы на сокет. Плюс я должен класть данные пришедшие на сокет в локальную базу данных для дальнейшего отображения списка контактов и чата с пользователем. На главной странице после авторизации я Созал МультиблокПровайдер
@override Widget build(BuildContext context) < return Scaffold( body: MultiBlocProvider( providers: [ BlocProvider( create: (context) => WebSocketBloc( webSocketRepo: RepositoryProvider.of(context)), ), BlocProvider( create: (context) => DbBloc( dbRepo: RepositoryProvider.of(context)), ), ], child: _transitionSwitcher(), ), bottomNavigationBar: BottomNavigationBar( type: BottomNavigationBarType.fixed, currentIndex: pageIndex, onTap: (value) < setState(() < pageIndex = value; >); >, items: [ BottomNavigationBarItem( icon: Icon(Icons.messenger), label: "Chats"), BottomNavigationBarItem(icon: Icon(Icons.people), label: "People"), BottomNavigationBarItem(icon: Icon(Icons.call), label: "Calls"), BottomNavigationBarItem( icon: httpGetLogoImage( SharedObjects.prefs! .getString(Constants.sessionProfilePictureUrl), 5), label: "Profile", ), ], )); >
- когда и в какой части кода инициализировать соединение с вебсокетом.
- Как полученные события из вебсокета передать в блок локальной бд чтобы он эти данные положил.
- Как после того как данные положились в локальную базу данных обновить блок контактов.
То есть все event создаются не UI а событием авторизации, когда пользователь успешно авторизировался идет запрос к вебсокету на запрос списка контактов. Слушатель стрима вебсокета принимает данные и кладет их в локальную базу данных, и после того как данные были добавлены в бд необходимо отобразить их на UI списка контактов.
Я возможно не совсем верно описал но надеюсь суть была понятна. Я новичок в dart.
Как сделать чат в реальном времени flutter + mysql?
как сделать чат на флутер ясно, как подключить приложение к mysql тоже ясно, а как организовать чат в реальном времени с mysql почему не firebase потому что мне чат написаный на ноде есть на сайте, я хочу сделать чат приложение для мобильных и синхронизировать его с сайтом??
- Вопрос задан более трёх лет назад
- 606 просмотров
3 комментария
Сложный 3 комментария
Neonoviiwolf @Neonoviiwolf
Александр Иванов @kiberchainik Автор вопроса
Neonoviiwolf, а по точнее?
Neonoviiwolf @Neonoviiwolf
Решения вопроса 0
Ответы на вопрос 1
nodejs developer / *nix admin
Для передачи сообщений клиентам в реальном времени используйте какой-нибудь Socket.IO.
В доках даже пример с чатом есть.
Собственно, библиотеки как для flutter, так и для nodejs есть. Полученные сообщения складывайте в БД, при подключении клиента к чату можно отдавать сообщения из БД или хранить в памати демона чата N последних сообщений и отдавать их, а БД лишь для истории.
Ответ написан более трёх лет назад
Комментировать
Нравится Комментировать
Ваш ответ на вопрос
Войдите, чтобы написать ответ

- MySQL
Как сделать сортировку по двум полям?
- 1 подписчик
- 15 часов назад
- 39 просмотров

- PHP
- +3 ещё
Как сделать быструю сортировку и фильтрацию товаров в bitrix с учетом скидок которые указаны в правилах корзины?
- 1 подписчик
- вчера
- 56 просмотров
Как сделать приложение чата на flutter сокетах
Бюджет: ожидает предложений
Дедлайн: 10.04.2023
Есть готовое приложение на flutter с чатом. Нужно дописать чат : перевести его с HTTP REST API на Web Socket. На стороне backend уже все готово и протестировано, нужно внести правки правки на уровне чата на flutter.
Опубликован:
29.03.2023 | 17:18 [поднят: 29.03.2023 | 17:18]
Заказ находится в архиве
Теги: нужен разработчик, ищу разработчика, резюме разработчика, требуется приложение под ios
© FL.ru, 2005 – 2024
© FL.ru, 2005 – 2024
Наши партнеры
Сведения об ООО «Ваан» внесены в реестр аккредитованных организаций, осуществляющих деятельность в области информационных технологий. ООО «Ваан» осуществляет деятельность, связанную с использованием информационных технологий, по разработке компьютерного программного обеспечения, предоставлению доступа к программе для ЭВМ и является правообладателем программы для ЭВМ «Платформа FL.ru (версия 2.0)».
Продолжая пользоваться сайтом, вы соглашаетесь с условиями использования файлов cookie