① 了解 Flutter 3.16 功能更新
Flutter 3.16 版本引入了多处关键更新,包括 Material 3 成为默认主题、Impeller 在 android 上的预览版发布以及为 DevTools 添加扩展支持等。此次更新收到社区积极反馈,三个月内共合并 928 个拉取请求,其中 40 名开发者贡献了新代码。
Material 3 更新
Material 库已升级至 3.10 版本,以匹配最新 Material Design 规范。默认启用 Material 3,用户可通过 MaterialApp 主题中的 useMaterial3 属性选择退出。新组件、主题和视觉效果引入,以支持 Material 3 风格。演示应用允许用户试用所有组件并切换 Material 3 模式。
性能改进
新增 Easing 和 Durations 类,改进 Material 3 动效。在 iOS 系统上,用户现在可在编辑菜单中添加查找、搜索和共享选项。文本缩放系数 TextScaler 提供了支持 Android 14 中的非线性字体缩放功能。SelectionArea 经过更新以支持鼠标和触屏设备上的原生手势。菜单项现在允许清除焦点更改,Mac 平台上的应用会遵循《Apple 人机界面指南》对快捷方式排序。
动画和测试支持
MatrixTransition widget 为变换转场动画提供了新方式,PaintPattern 类用于验证 CustomPainter 和 Decoration 的绘制调用。滚动更新引入 KeepAlive widget、默认焦点遍历和隐式滚动支持。二维滚动基础改进,支持构建 2D 滚动 widget。
Impeller 发展
Impeller 已在 Android 上准备好预览版,Android 开发者可使用— enable-impeller 标志尝试。在支持 Vulkan 的设备上,Impeller 表现良好,团队计划未来为 OpenGL 后端提供功能,并征集反馈。Impeller 的 Vulkan 后端在某些设备上显示出改进的性能和稳定性。
游戏开发工具包
更新的休闲游戏工具包提供了一系列资源,帮助开发者构建概念到发布的游戏,包括纸牌游戏、跑酷游戏以及对 Google Play 游戏服务、应用内购买、广告等服务的支持。
Web 和 Android 更新
Chrome DevTools 中新增 Flutter 时间轴事件,改善了 Web 应用的调试性能。Android 支持鼠标滚轮滚动速度与设备匹配,引入预测性返回手势。应用扩展功能允许开发者使用 Flutter widget 在某些 iOS 应用扩展上绘制界面。
包生态系统
Flutter Favorite 项目重新启动,新包包括 flame、flutter_animate 等。首次举办 package 生态系统网络峰会,超过 50 名非 Google 员工和贡献者参与讨论。基于 Cloud 的 Google 地图样式无需代码更新即可自定义。CameraX 支持改进,macOS 视频播放器添加支持。
DevTools 更新
DevTools 扩展框架支持新 package,如 Provider、Drift 和 Patrol。版本更新包括性能改进和 DevTools 扩展功能。
即刻体验
Flutter 3.16 现已发布至稳定渠道,包括 Dart 3.2。只需使用 flutter upgrade 即可获取最新更新。
② TCP keepalive 和 http keep-alive 以及心跳保活
HTTP的长连接和短连接本质上是TCP长连接和短连接。
短连接
短连接,顾名思义,与长连接的区别就是,客户端收到服务端的响应后,立刻发送FIN消息,主动释放连接。也有服务端主动断连的情况,凡是在一次消息交互(发请求-收响应)之后立刻断开连接的情况都称为短连接。
长连接/http keep-alive
也叫持久连接,即一个TCP连接服务多次请求,在TCP层握手成功后,不立即断开连接,并在此连接的基础上进行多次消息(包括心跳)交互,直至连接的任意一方(客户端OR服务端)主动断开连接,此过程称为一次完整的长连接。
在HTTP/1.0中得到了初步的支持,客户端在请求header中携带Connection:Keep-Alive,即是在向服务端请求持久连接。如果服务端接受持久连接,则会在响应header中同样携带Connection: Keep-Alive,这样客户端便会继续使用同一个TCP连接发送接下来的若干请求。(Keep-Alive的默认参数是[timout=5, max=100],即一个TCP连接可以服务至多5秒内的100次请求)
HTTP/1.1开始,即使请求header中没有携带Connection: Keep-Alive,传输也会默认以持久连接的方式进行,只有加入"Connection: close "后,才关闭。
http keepalive是客户端浏览器与服务端httpd守护进程协作的结果。
TCP中的KeepAlive
TCP协议的实现中,提供了KeepAlive报文,用来探测连接的对端是否存活。在应用交互的过程中,可能存在以下几种情况:
客户端或服务器意外断电,死机,崩溃,重启;
中间网络已经中断,而客户端与服务器并不知道;
利用保活探测功能,可以探知这种对端的意外情况,从而保证在意外发生时,可以释放半打开的TCP连接。TCP保活报文交互过程如下:
因此,KeepAlive并不适用于检测双方存活的场景,这种场景还得依赖于应用层的心跳。 应用层心跳也具备着更大的灵活性,可以控制检测时机,间隔和处理流程,甚至可以在心跳包上附带额外信息。
应用层心跳是检测连接有效性以及判断双方是否存活的有效方式 。但是心跳过于频繁会带来 耗电和耗流量 的弊病,心跳频率过低则会影响连接检测的实时性。业内关于心跳时间的设置和优化,主要基于如下几个因素:
理想的情况下,客户端应当以略小于NAT超时时间的间隔来发送心跳包。 根据微信团队测试的一些数据,一些常用网络的NAT超时时间如下表所示:
TCP的KeepAlive机制意图在于保活、心跳,检测连接错误
如何快速区分当前连接使用的是长连接还是短连接
1、凡是在一次完整的消息交互(发请求-收响应)之后,立刻断开连接(有一方发送FIN消息)的情况都称为短连接;
2、长连接的一个明显特征是会有心跳消息(也有没有心跳的情况),且一般心跳间隔都在30S或者1MIN左右,用wireshark抓包可以看到有规律的心跳消息交互(可能会存在毫秒级别的误差)。
什么时候用长连接,短连接?
1、需要频繁交互的场景使用长连接,如即时通信工具(微信/QQ,QQ也有UDP),相反则使用短连接,比如普通的web网站,只有当浏览器发起请求时才会建立连接,服务器返回相应后,连接立即断开。
2、维持长连接会有一定的系统开销,用户量少不容易看出系统瓶颈,一旦用户量上去了,就很有可能把服务器资源(内存/CPU/网卡)耗尽,所以使用需谨慎。
keep-alive与TIME_WAIT
使用http keep-alvie,可以减少服务端TIME_WAIT数量(因为由服务端httpd守护进程主动关闭连接)。道理很简单,相较而言,启用keep-alive,建立的tcp连接更少了,自然要被关闭的tcp连接也相应更少了。
短连接和长链接 图:
参考: https://caofengbin.github.io/2018/03/16/dhcp-and-nat/#4-%E5%BD%B1%E5%93%8D%E5%BF%83%E8%B7%B3%E9%A2%91%E7%8E%87%E7%9A%84%E5%85%B3%E9%94%AE%E5%9B%A0%E7%B4%A0
https://blog.csdn.net/hengyunabc/article/details/44310193
http://wingjay.com/2018/12/05/android-arch-long-link/
https://www.levicc.com/2018/06/30/yi-dong-an-wang-luo-you-hua/
能被我参考的都很优秀,哈哈
③ RouterOSv7WireGuard隧道协议
RouterOS v7加入了WireGuard,WireGuard是一个极简而快速的加密VPN协议。其设计目标是比IPsec更快、更精简和高效,同时性能要比OpenVPN提升很多。WireGuard被设计成一种通用VPN,可以在多个平台上运行,适合许多不同的环境。最初是为Linux内核发布的,后支持跨平台(Windows, macOS, BSD, iOS, Android),能进行广泛的部署。
从官方测试性能看,WireGurad对于IPsec优势非常明显,而对于OpenVPN几乎是碾压。
在部署方面,WireGurad各个节点是Peer对等体的概念,而非是Server与Client关系,相互之间是对等的,一个节点既可以是发起者,也可以是接收者,比如网上提到VPN的拓扑方案中,可以是点对点,点对多点的中心覆盖,而WireGuard不一样了,不仅可以点对点,也可以点对多点,每个节点同时可连接多个 Peer,看到过有人通过WireGuard建立全互联模式,三层的Mesh网状网络。
WireGuard只支持UDP协议,不支持传统的TCP-over-TCP隧道,因为TCP网络性能并不理想,如果对TCP连接有需求,将wiredguard的UDP包转换为TCP,并可以使用如udptunnel和udp2raw来协助完成。
关于NAT穿透,通常情况下,WireGuard网络在未被使用的情况下,会尽量保持“安静”。在大多数情况下,它只在Peer对等体,希望发送数据包时传输数据,当它没有被要求发送数据包时,它就停止发送,直到再次被请求。在点对点公网IP连接的网络环境是这样的,然而,当一个Peer端位于NAT或防火墙之后时,即使它不发送任何数据包的情况下,也希望能接收传入的数据包。因为NAT和防火墙会跟踪“会话连接”,他必须通过定期发送数据包来维持NAT/防火墙连接会话映射的有效,即UDP的timeout时间,即被称为keepalive。WireGuard可以开启此选项,每隔一秒向对端点发送一个keepalive报文,当然适用于各种NAT/防火墙的合理间隔在25秒。默认设置keepalive是关闭状态,因为公网IP连接的用户不需要这个功能。
WireGuard加密使用ChaCha20,验证使用Poly1305,它几乎在所有通用CPU上的运行速度都非常快。虽然未被专用硬件支持(IPsec支持硬件加速),但在CPU上的矢量指令(vector instructions)与AES-NI指令处于相同的优先级(有时甚至更快)。
总结下WireGuard的特点:
是基于UDP协议连接,具备网络性能优势
运行在Linux内核,在性能上优于IPsec和OpenVPN
每个节点通过公钥识别进行验证,加密采用的是ChaCha20Poly1305。
每个节点是平等的,既可以作为server,又可以作为client
两端仅需要一个配置公网IP,另一端在nat后也能连接,nat后的节点,仅需要对端节点公钥,以及公网IP (endpoint)和端口(endpoint port),而公网节点只需要填写连接端的公钥即可
从测试结果看未使用IPsec加密的L2TP的传输带宽性能最好,超过了WireGuard,但在使用IPsec的L2TP加密后,性能远不如WireGuard,我平时喜欢使用SSTP在RouterOS设备之间建立连接,因为SSTP端口灵活,在RouterOS建立隧道无需证书,但SSTP的传输性能在RouterOS支持的所有隧道协议中性能是最差的,现在v7有了WireGuard就不一样了。
④ android socket有几种方法
/***第一种:客户端Socket通过构造方法连接服务器***/
//客户端Socket可以通过指定IP地址或域名两种方式来连接服务器端,实际最终都是通过IP地址来连接服务器
//新建一个Socket,指定其IP地址及端口号
Socket socket = new Socket("192.168.0.7",80);
/***Socket 客户端 一些常用设置***/
//客户端socket在接收数据时,有两种超时:1.连接服务器超时,即连接超时;2.连接服务器成功后,接收服务器数据超时,即接收超时
//*设置socket 读取数据流的超时时间
socket.setSoTimeout(5000);
//发送数据包,默认为false,即客户端发送数据采用Nagle算法;
//但是对于实时交互性高的程序,建议其改为true,即关闭Nagle算法,客户端每发送一次数据,无论数据包大小都会将这些数据发送出去
socket.setTcpNoDelay(true);
//设置客户端socket关闭时,close()方法起作用时延迟1分钟关闭,如果1分钟内尽量将未发送的数据包发送出去
socket.setSoLinger(true, 60);
//设置输出流的发送缓冲区大小,默认是8KB,即8096字节
socket.setSendBufferSize(8096);
//设置输入流的接收缓冲区大小,默认是8KB,即8096字节
socket.setReceiveBufferSize(8096);
//作用:每隔一段时间检查服务器是否处于活动状态,如果服务器端长时间没响应,自动关闭客户端socket
//防止服务器端无效时,客户端长时间处于连接状态
socket.setKeepAlive(true);
/*** Socket客户端向服务器端发送数据 ****/
//客户端向服务器端发送数据,获取客户端向服务器端输出流
OutputStream os = socket.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(os);
BufferedWriter bw = new BufferedWriter(osw);
//代表可以立即向服务器端发送单字节数据
socket.setOOBInline(true);
//数据不经过输出缓冲区,立即发送
socket.sendUrgentData(65);//"A"
//向服务器端写数据,写入一个缓冲区
//注:此处字符串最后必须包含“\r\n\r\n”,告诉服务器HTTP头已经结束,可以处理数据,否则会造成下面的读取数据出现阻塞
//在write()方法中可以定义规则,与后台匹配来识别相应的功能,例如登录Login()方法,可以写为write("Login|test,123 \r\n\r\n"),供后台识别;
bw.write("Login|test,123 \r\n\r\n");
//发送缓冲区中数据,必须有
bw.flush();
/*** Socket客户端读取服务器端响应数据 ****/
//socket.isConnected代表是否连接成功过
if((socket.isConnected() == true) && (socket.isClosed() == false)){//判断Socket是否处于连接状态
//客户端接收服务器端的响应,读取服务器端向客户端的输入流
InputStream is = socket.getInputStream();
//缓冲区
byte[] buffer = new byte[is.available()];
//读取缓冲区
is.read(buffer);
//转换为字符串
String responseInfo = new String(buffer);
//日志中输出
Log.i("TEST", responseInfo);
} //关闭网络
socket.close();
/***第二种:通过connect方法连接服务器***/
Socket socket_other = new Socket();
//使用默认的连接超时
socket_other.connect(new InetSocketAddress("192.168.0.7",80));
//连接超时2s
socket_other.connect(new InetSocketAddress("192.168.0.7",80),2000);
//关闭socket
socket_other.close();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}