Flutter开发进阶之使用Socket实现主机服务(二)

news/2024/7/20 22:10:17 标签: flutter, android, 网络, dart, ios

Flutter开发进阶之使用Socket实现主机服务(二)

Flutter开发进阶之使用Socket实现主机服务(一)
在完成局域网内设备定位后就可以进入微服务的实操了。
在这里插入图片描述

I、构建Socket连接池

一、定义Socket

使用socket_io_client

socket_io_client: ^2.0.3+1

导入头文件

dart">import 'package:socket_io_client/socket_io_client.dart' as io;

定义属性

dart">class _SocketIoObject {
  /// 连接
  io.Socket? socket; 
  /// 连接次数
  int count = 0; 
  /// 创建的时间
  int createTime = 0; 
  /// 根据连接频率获取的优先级
  double proportion = 0; 
}

二、定义连接池

dart">class SocketIoPool {
  /// 连接池本身
  static Map<String, dynamic> sockets = {}; 
  /// 连接最大数量
  static int maxCount = 10; 
  /// 根据优先级获取到
  /// 最应该销毁的连接的key
  static String exitKey = ""; 
}

三、连接池运行逻辑

连接排序

dart">/// 将连接按照优先级排序
/// 使用频率越低的连接的优先级越高
/// 可以被销毁
/// 
static void _sortSocket() {
    int now = DateTime.now().millisecondsSinceEpoch;
    double maxProportion = 0;
    sockets.forEach((key, value) {
      value.proportion = (now - value.createTime) / value.count;
      if (value.proportion > maxProportion) {
        maxProportion = value.proportion;
        exitKey = key;
      }
    });
  }

连接创建

dart">/// 创建新连接时限制最大连接数量
/// 
static io.Socket _newSocket(String host, int port) {
    if (sockets.length >= maxCount && exitKey.isNotEmpty) {
      _SocketIoObject? object = sockets[exitKey];
      if (object != null) {
        object.socket?.disconnect();
        object.socket?.dispose();
        sockets.remove(exitKey);
      }
    }
    String relative = "$host:$port";
    io.Socket socket = io.io(relative);
    sockets[relative] = _SocketIoObject()
      ..socket = socket
      ..count = 1
      ..createTime = DateTime.now().millisecondsSinceEpoch;
    Future(() => _sortSocket());
    return socket;
  }

连接获取

dart">/// 尽量复用连接
/// 没有再创建
/// 
static io.Socket? getSocket(String host, int port) {
    String relative = "$host:$port";
    if (sockets.containsKey(relative)) {
      sockets[relative]?.count++;
      Future(() => _sortSocket());
      return sockets[relative]?.socket;
    }
    return _newSocket(host, port);
  }

II、构建数据库

一、对应表的创建

使用sqflite

sqflite: ^2.3.2

导入头文件

dart">import 'package:sqflite/sqflite.dart';

定义表

dart">class Animal {
  int? id;
  int? age;
  double? height;
  int? gender;
  String? name;
  String? species;
  String? family;

  Animal({
    this.id,
    this.age,
    this.height,
    this.gender,
    this.name,
    this.species,
    this.family,
  });
  
  factory Animal.fromJson(Map<String, dynamic> map) {
    return Animal(
        id: map["id"],
        age: map["age"],
        height: map["height"],
        gender: map["gender"],
        name: map["name"],
        species: map["species"],
        family: map["family"]);
  }
  
  /// 类名
  static String className<T>() {
    return T.toString();
  }
  
  /// 创建表
  static Future<void> createTable(Database db) async {
    final batch = db.batch();
    batch.execute(createTableSql);
    await batch.commit();
  }
}

注意:为提高并发性能,尽量使用事务管理,

When committed with [Batch.commit], sqflite will manage a transaction to
execute statements in the batch. If this [batch] method has been called on a [Transaction], committing the batch is deferred to when the transaction
completes (but [Batch.apply] or [Batch.commit] still need to be called).

体现在sqflite中就是使用Batch或者transaction。

二、定义sql语句

dart">/// 插入数据
  String get insertSql =>
      "INSERT OR REPLACE INTO ${Animal.className()} (id,age,height,gender,name,species,family) VALUES ($id,$age,$height,$gender,$name,$species,$family)";

  /// 更新数据
  String get updateSql =>
      "UPDATE ${Animal.className()} SET age = $age, height = $height, gender = $gender, name = $name, species = $species, family = $family WHERE id = $id";

  /// 删除数据
  String get deleteSql => "DELETE FROM ${Animal.className()} WHERE id = $id";

  /// 查询所有
  static String get allSql => "SELECT * FROM ${Animal.className()}";

  /// 删除表
  static String get clearSql => "DROP TABLE ${Animal.className()}";

  /// 查询某条
  static String get oneSql =>
      "SELECT * FROM ${Animal.className()} WHERE id = ?";

三、定义数据库管理器

dart">class SqfliteManager {
  /// 数据库名称 一般为xx.db
  String dbName;
  /// 数据库版本
  int version;

  SqfliteManager({
    required this.dbName,
    required this.version,
  });
}

数据库的获取

dart">  Database? _database;

  Future<String> get _databasePath async {
    final databasePath = await getDatabasesPath();
    return "$databasePath/$dbName";
  }

  /// 获取数据库
  Future<Database?> get database async {
    if (_database == null) {
      String path = await _databasePath;
      _database =
          await openDatabase(path, version: version, onCreate: (db, v) async {
        /// 创建数据库时
      }, onConfigure: (db) {
        /// 数据库配置时,在创建前、升降级前
      }, onDowngrade: (db, oldV, newV) {
        /// 数据库降级时
      }, onUpgrade: (db, oldV, newV) {
        /// 数据库升级时
      }, onOpen: (db) {
        /// 数据库打开时
      });
    }
    return _database;
  }

四、对应的数据库操作指令

dart">/// 销毁数据库
  Future<void> cancelDatabase() async {
    String path = await _databasePath;
    return deleteDatabase(path);
  }

  /// 数据库关闭
  Future<void> closeDatabase() async {
    if (_database?.isOpen == true) {
      await _database?.close();
    }
    _database = null;
  }

  /// 插入动物数据
  Future<void> insertAnimal(Animal animal) async {
    await database.then(
      (db) async => await db?.transaction(
        (txn) async => await txn.rawInsert(animal.insertSql),
      ),
    );
  }

  /// 更新动物数据
  Future<void> updateAnimal(Animal animal) async {
    await database.then(
      (db) async => await db?.transaction(
        (txn) async => await txn.rawUpdate(animal.updateSql),
      ),
    );
  }

  /// 删除动物数据
  Future<void> deleteAnimal(Animal animal) async {
    await database.then(
      (db) async => await db?.transaction(
        (txn) async => await txn.rawDelete(animal.deleteSql),
      ),
    );
  }

  /// 查询所有动物数据
  Future<List<Animal>?> allAnimals() async {
    final db = await database;
    final batch = db?.batch();
    batch?.rawQuery(Animal.allSql);
    List<Map<String, dynamic>>? maps =
        await batch?.commit() as List<Map<String, dynamic>>?;
    return maps?.map((e) => Animal.fromJson(e)).toList();
  }

  /// 删除动物数据表
  Future<void> deleteAnimalTable() async {
    await database.then(
      (db) async => await db?.transaction(
        (txn) async => await txn.rawDelete(Animal.clearSql),
      ),
    );
  }

  /// 查询单条动物数据
  Future<Animal?> findAnimal(int id) async {
    final db = await database;
    final batch = db?.batch();
    batch?.rawQuery(Animal.oneSql, [id]);
    List<Map<String, dynamic>>? maps =
        await batch?.commit() as List<Map<String, dynamic>>?;
    return maps?.map((e) => Animal.fromJson(e)).toList().first;
  }

III、执行通讯

dart">    final a = SocketIoPool.getSocket('http://192.168.0.1', 80);
    a?.connect();
    a?.on('getAnimals', (data) {
      a.emit('getAnimalsResponse', {data: animals});
    });

http://www.niftyadmin.cn/n/5445031.html

相关文章

Springboot vue elementui 超市管理系统

Springboot vue elementui 超市管理系统 点击获取项目全套源码

PostgreSQL和MySQL的异同

0.前言 MySQL是一个关系数据库管理系统&#xff08;DBMS&#xff09;&#xff0c;通过该系统&#xff0c;您可以将数据存储为包含行和列的二维表格。它是一个常用系统&#xff0c;支持许多 Web 应用程序、动态网站和嵌入式系统。PostgreSQL 是一个对象关系数据库管理系统&…

2024年03月CCF-GESP编程能力等级认证C++编程一级真题解析

本文收录于专栏《C++等级认证CCF-GESP真题解析》,专栏总目录:点这里。订阅后可阅读专栏内所有文章。 一、单选题(每题 2 分,共 30 分) 第 1 题 C++表达式 (3 - 2) * 3 + 5 的值是( )。 A. -13 B. 8 C. 2 D. 0 答案:B 第 2 题 C++语句 cout << “5%2=” <&l…

网络基础(一)初识

1、计算机网络背景 1.1、网络发展 1. 独立模式: 计算机之间相互独立&#xff1b; 2. 网络互联: 多台计算机连接在一起&#xff0c;完成数据共享&#xff1b; 3. 局域网LAN: 计算机数量更多了, 通过交换机和路由器连接在一起; 4. 广域网WAN: 将远隔千里的计算机都连在一起;…

洛谷入门——P1567 统计天数

统计天数 题目描述 炎热的夏日&#xff0c;KC 非常的不爽。他宁可忍受北极的寒冷&#xff0c;也不愿忍受厦门的夏天。最近&#xff0c;他开始研究天气的变化。他希望用研究的结果预测未来的天气。 经历千辛万苦&#xff0c;他收集了连续 N ( 1 ≤ N ≤ 1 0 6 ) N(1 \leq N …

【CPP】C++11多线程

thread类 在C11之前&#xff0c;涉及到多线程问题&#xff0c;都是和平台相关的&#xff0c;比如windows和linux下各有自己的接口&#xff0c;这使得代码的可移植性比较差。C11中最重要的特性就是对线程进行支持了&#xff0c;使得C在并行编程时不需要依赖第三方库&#xff0c…

【鸿蒙HarmonyOS开发笔记】动画过渡效果之组件内转场动画,内含ForEach动画

概述 我们在开发中难免设计组件的插入、删除过程。通过组件内转场动画&#xff0c;可定义组件出现、消失的效果。 组件内转场动画的接口为&#xff1a; transition(value: TransitionOptions)transition函数的入参为组件内转场的效果&#xff0c;可以定义平移、透明度、旋转…

羊大师羊奶靠谱么?消费口碑深度讲解

羊大师羊奶靠谱么&#xff1f;消费口碑深度讲解 羊大师羊奶&#xff0c;作为羊奶市场的一颗璀璨明星&#xff0c;其靠谱性一直备受广大消费者的关注。那么&#xff0c;羊大师羊奶究竟靠不靠谱呢&#xff1f;这需要我们从品牌实力与消费口碑两个方面进行深度解析。 从品牌实力来…