大庆商城网站建设网站建设带数据库模板

当前位置: 首页 > news >正文

大庆商城网站建设,网站建设带数据库模板,辽宁平台网站建设公司,中山网站建设 7601.起因 起因是年前看到了一篇Rust iOS Android#xff5c;未入门也能用来造轮子#xff1f;的文章#xff0c;作者使用Rust做了个实时查看埋点的工具。其中作者的一段话给了我启发#xff1a; 无论是 LookinServer 、 Flipper 等 Debug 利器#xff0c;还是 Flutt… 1.起因 起因是年前看到了一篇Rust iOS Android未入门也能用来造轮子的文章作者使用Rust做了个实时查看埋点的工具。其中作者的一段话给了我启发 无论是 LookinServer 、 Flipper 等 Debug 利器还是 Flutter / Web Debug Tools都是在电脑上调试 App。那我们也可以用类似的方式把实时埋点数据显示在电脑上不再局限于同一块屏幕。 我司目前的埋点走查是在测试盒子中有一个埋点查看页面Debug包在数据上报的同时会将信息临时保存起来。当进入这个页面时会以列表的形式展示出来。并且iOS 和Android的页面展示和使用方式也略有不同。 后面我觉得这样进入退出页面查看不方便就将页面改成了悬浮窗。虽然方便了一些但是也发现了新的问题 手机上屏幕大小有限悬浮窗只有屏幕的一半可展示信息有限。悬浮窗会遮挡页面有时不便于点击页面上的按钮。 刚好前阵子升级了手机系统到Android 13发现log在控制台都打印不出来了后面发现App适配到13就正常了。。。所以有了一个想法使用Rust通过WebSocket进行数据发送使用Flutter实现服务端接收App发送的信息并显示出来。 当然了如果我们的应用是flutter写的可以直接使用Dart的ffi来直接调用Rust函数。这个我后面有时间会单独写一篇来分享。 2.实现 之所以选择Rust与Flutter是看中它们的跨平台能力。使用Rust进行WebSocket数据发送就不用Android和iOS端去重复开发这个功能只需要简单调用即可并且Rust有许多开箱即用的库。 Flutter的跨平台能力就更不用说了。比如这个小工具我就可以一套代码输出Windows和macOS两个平台的安装包保证接收端逻辑和UI的一致。 发送端 Rust部分 关于Rust库的打包以及双端的使用可以看我上一篇分享的Rust库交叉编译以及在Android与iOS使用。这里主要说一下具体的实现代码。 首先是添加WebSocket 库 ws-rs依赖到Cargo.toml文件 [dependencies] ws 0.9.2

全局的静态变量

lazy_static 1.4.0实现代码如下 use std::collections::HashMap; use std::sync::Mutex; use std::{ffi::CStr, os::raw::c_char}; use ws::{connect, Handler, Sender, Handshake, Result, Message, CloseCode, Error}; use ws::util::Token; #[macro_use] extern crate lazy_static;lazy_static! {static ref DATA_MAP: MutexHashMapString, Sender {let map: HashMapString, Sender HashMap::new();Mutex::new(map)}; }struct Client {sender: Sender,host: String, }impl Handler for Client {fn on_open(mut self, _: Handshake) - Result() {DATA_MAP.lock().unwrap().insert(self.host.to_owned(), self.sender.to_owned());Ok(())}fn on_message(mut self, msg: Message) - Result() {println!(receive {}. , msg);Ok(())}fn on_close(mut self, _code: CloseCode, _reasonn: str) {DATA_MAP.lock().unwrap().remove(self.host);}fn on_timeout(mut self, _event: Token) - Result() {DATA_MAP.lock().unwrap().remove(self.host);self.sender.shutdown().unwrap();Ok(())}fn on_error(mut self, _err: Error) {DATA_MAP.lock().unwrap().remove(self.host);}fn on_shutdown(mut self) {DATA_MAP.lock().unwrap().remove(self.host);}}#[no_mangle] pub extern C fn websocket_connect(host: *const c_char) {let c_host unsafe { CStr::from_ptr(host) }.to_str().unwrap();if let Err(err) connect(c_host, |out| {Client {sender: out,host: c_host.to_string(),}}) {println!(Failed to create WebSocket due to: {:?}, err);} }#[no_mangle] pub extern C fn send_message(host: *const c_char, message: *const c_char) {let c_message unsafe { CStr::from_ptr(message) }.to_str().unwrap();let c_host unsafe { CStr::from_ptr(host) }.to_str().unwrap();let binding DATA_MAP.lock().unwrap();let sender binding.get(c_host.to_string());match sender {Some(s) {if s.send(c_message).is_err() {println!(Websocket couldnt queue an initial message.)};} ,None println!(None)} }#[no_mangle] pub extern C fn websocket_disconnect(host: const c_char) {let c_host unsafe { CStr::from_ptr(host) }.to_str().unwrap();DATA_MAP.lock().unwrap().remove(c_host.to_string()); }简单实现了连接发送断开连接三个方法。思路是连接成功后会将发送结构体Sender保存在Map中每次发送时先检查是否连接再发送。这样也就实现了连接多台设备一对多发送的功能。 Android还需要添加对应的JNI方法 #[cfg(target_os android)] #[allow(non_snake_case)] pub mod android {extern crate jni;use self::jni::objects::{JClass, JString};use self::jni::JNIEnv;use super::;#[no_mangle]pub unsafe extern C fn Java_com_weilu_utils_EventLogUtilssendMessage(env: JNIEnv,: JClass,host: JString,message: JString,) {send_message(env.get_string(host).expect(invalid pattern string).as_ptr(),env.get_string(message).expect(invalid pattern string).as_ptr(),);}#[no_mangle]pub unsafe extern C fn Java_com_weilu_utils_EventLogUtilsconnect(env: JNIEnv,: JClass,host: JString,) {websocket_connect(env.get_string(host).expect(invalid pattern string).as_ptr(),);}#[no_mangle]pub unsafe extern C fn Java_com_weilu_utils_EventLogUtilsdisconnect(env: JNIEnv,: JClass,host: JString,) {websocket_disconnect( env.get_string(host).expect(invalid pattern string).as_ptr(),);} }至此发送端部分完成。打包集成进项目就可以使用了。 Android部分 Android端调用代码如下 public class EventLogUtils {static {System.loadLibrary(event_log_kit);}private static native void sendMessage(final String host, final String message);private static native void connect(final String host);private static native void disconnect(final String host);private static ListString addressList null;public static ListString getAddressList() {return addressList;}/*** 保存 IP 地址传空时断开所有连接/public static void saveAddress(String address) {if (TextUtils.isEmpty(address)) {if (addressList ! null) {for (String url : addressList) {disconnect(url);}}addressList null;return;}// 多个地址逗号隔开if (address.contains(,)) {addressList new ArrayList(Arrays.asList(address.split(,)));} else {addressList new ArrayList();addressList.add(address);}for (String url : addressList) {// 子线程调用可替换为其他方案这里使用了线程池Executor.getExecutor().getExecutorService().submit(new Runnable() {Overridepublic void run() {// 循环如果意外断开自动重连while (addressList ! null) {connect(ws:// url);}// 工具连接彻底断开}});}}/** 发送信息*/public static void sendMessage(String message) {if (addressList null) {return;}for (String url : addressList) {sendMessage(ws:// url, message);}} } 代码也比较简单连接方法在子线程调用如果发现连接断开会自动重连。 iOS部分就不具体说明了实现思路一样的。 接收端 首先是发送数据的定义发送的是json格式字符串。定义的主要参数如下 class EventLogEntity {/// event/logString type ;/// 事件名称或log tagString? name;/// 手机型号String? deviceModel;/// 时间戳int time 0;String data ;… }type用于区分数据类型目前分为埋点事件与log。name事件名称或log tag用于数据的筛选。deviceModel设备名用于区分数据来源如果有多个设备同时发送数据可以便于分类。time时间戳用于数据排序。 其他参数可以根据自己的需求添加比如log的等级数据展示时展开或者收起。 UI组件我使用了fluent_ui它提供了原生Windows应用风格的组件比较适合桌面端程序。状态管理使用flutter_riverpod。 具体的代码实现就不多说了主要说一下核心的数据接收部分。 // https://doc.xuwenliang.com/docs/dart-flutter/2499 class WebSocketManager{HttpServer? requestServer;Future startWebSocketListen() async {final String ip 192.168.31.232;final String port 51203;stopWebSocketListen();//HttpServer.bind(主机地址端口号)requestServer await HttpServer.bind(ip, int.parse(port)).catchError((error) {debugPrint(bind error: \(error);});await for(HttpRequest request in requestServer!) {serveRequest(request).catchError((error){debugPrint(listen error: \)error);});}}void stopWebSocketListen() {requestServer?.close();requestServer null;}Future serveRequest(HttpRequest request) {//判断当前请求是否可以升级为WebSocketif (WebSocketTransformer.isUpgradeRequest(request)) {//升级为webSocketreturn WebSocketTransformer.upgrade(request).then((webSocket) {//webSocket消息监听webSocket.listen((msg) async {debugPrint(listen:$msg);if (webSocket.closeCode null) {// 这里可以回复客户端消息webSocket.add(收到);}// 可以在这里解析数据刷新页面…});});} else {return Future((){});}} }然后为了便于使用避免使用者自己查询填写ip我们需要获取当前设备ip地址 FutureString getDeviceIp() async {String ip ;if (!kIsWeb) {for (var interface in await NetworkInterface.list()) {for (var address in interface.addresses) {ip address.address;}}}return ip;}端口可以给个默认值或者自己随便输入一个然后可以用shared_preferences插件保存用户配置。下次启动时就自动连接了。 手机端可以实现一个输入连接地址的页面输入电脑端的ip和端口号后就可以发送数据了。或者扫描二维码连接。 3.成果展示 目前实现功能如下 可同时接收多台设备发送数据数据按机型名称分类展示。数据的筛选搜索关键字高亮。搜索记录的保存。json数据格式化展示。 因为小工具在公司内部使用所以就不开源完整的代码了。有了文章中的核心代码你可以根据自己的需求实现。也不必局限于这些功能你完全可以通过Rust和Flutter的跨平台能力开发更多功能本篇也只是抛砖引玉。 如果本篇对你有所启发帮助不妨点赞支持一下。如果你有好的想法也欢迎评论交流。 4.参考 Rust iOS Android未入门也能用来造轮子