首页
苏兮影视
随笔记
壁纸
更多
直播
时光轴
友联
关于
统计
Search
1
软件添加id功能按钮
708 阅读
2
v2ray节点搭建
508 阅读
3
typecho非常有特色的模块
460 阅读
4
QQxml消息卡片生成源码
421 阅读
5
Linux下提权常用小命令
366 阅读
谈天说地
建站源码
经验教程
资源分享
动漫美图
登录
Search
标签搜索
java
flutter
springboot
rust
安卓
linux
vue
docker
joe
快捷键
git
fish shell
maven
redis
netty
dart
groovy
js
设计模式
rpc
尽意
累计撰写
95
篇文章
累计收到
38
条评论
首页
栏目
谈天说地
建站源码
经验教程
资源分享
动漫美图
页面
苏兮影视
随笔记
壁纸
直播
时光轴
友联
关于
统计
搜索到
95
篇与
的结果
2025-01-16
我的世界低延迟联机
此方案需要服务器,主要针对国外服务器,一般延迟比较高,使用服务器部署frps服务端,充当中间信令服务器,反向代理服务器实现原理通过frp的p2p点对点连接实现低延迟联机操作步骤软件下载下载对应的frp软件,服务器,本地设备(Windows,安卓)都需要下载https://github.com/fatedier/frp/releases配置服务器端服务器端的配置文件frps.toml[common] bind_port = 10008 enable_p2p = true启动服务器的frps# frps的当前目录运行,指定配置文件路径 ./frps -c frps.toml输出frps started successfully就启动成功了配置客户端(被访问端)即开服的设备(Windows,安卓termux)配置文件server.toml# 服务器的域名或ip地址 serverAddr = "x.x.x.x" serverPort = 10008 # 如果默认的 STUN 服务器不可用,可以配置一个新的 STUN 服务器 # natHoleStunServer = "xxx" [[proxies]] name = "p2p_mc" type = "xtcp" # 只有共享密钥 (secretKey) 与服务器端一致的用户才能访问该服务 secretKey = "aaaaa" localIP = "127.0.0.1" # 我的世界服务器的端口 localPort = 25565启动客户端的fprc# cmd输入 frpc.exe -c server.toml配置客户端(访问者端)配置文件client.tomlserverAddr = "x.x.x.x" serverPort = 10008 # 如果默认的 STUN 服务器不可用,可以配置一个新的 STUN 服务器 # natHoleStunServer = "xxx" [[visitors]] name = "p2p_mc_visitor" type = "xtcp" # 要访问的 P2P 代理的名称 serverName = "p2p_mc" secretKey = "aaaaaa" # 绑定本地端口以访问 远程服务 bindAddr = "127.0.0.1" bindPort = 6000 # 如果需要自动保持隧道打开,将其设置为 true # keepTunnelOpen = false启动客户端的frpc# cmd输入 frpc.exe -c client.toml验证是否可以成功建立p2p连接命令行输入curl localhost:6000看到这个提示则表示成功建立了连接客户端连接我的世界服务器的地址为localhost:6000
2025年01月16日
4 阅读
0 评论
2 点赞
Linux 使用 screen
在Linux环境中,screen 是一个非常实用的终端多路复用工具,它可以让你在一个终端窗口中同时运行多个会话,并且能够在不同会话之间切换。screen 使得你可以保持任务在后台运行,甚至在断开 SSH 连接后,依然能够继续执行这些任务。1. 安装 screen大多数Linux发行版默认都提供了 screen 软件包。如果你的系统上没有安装,可以使用如下命令进行安装:Debian/Ubuntu 系统:sudo apt-get install screenCentOS/RHEL 系统:sudo yum install screenArch 系统:sudo pacman -S screen2. 启动 screen运行 screen 时,它会启动一个新的会话,并将你带入一个新的虚拟终端。基本的启动命令如下:screen此时,你会进入一个新的会话,你可以在这个会话中运行任何命令。你可以通过按下 Ctrl+A 再按 C 来创建一个新的虚拟终端。每个虚拟终端都有自己的命令行。3. 基本命令和操作创建新会话按下 Ctrl+A 然后按 C,这将创建一个新的窗口,你可以在新窗口中继续执行命令。切换会话切换到下一个窗口:Ctrl+A 然后按 N(next)切换到上一个窗口:Ctrl+A 然后按 P(previous)切换到指定窗口:Ctrl+A 然后按数字键(0-9)分离会话如果你想将会话挂起,并返回到主终端,使用以下命令:Ctrl+A d这会把当前会话分离(detach),你可以在后续任何时候重新连接到它。恢复会话要恢复一个已经分离的会话,使用:screen -r如果有多个会话,你需要指定会话ID:screen -r <会话ID>关闭会话要关闭当前会话,可以直接退出会话中的 shell(例如 exit 或 Ctrl+D)。会话关闭后,所有在该会话中运行的程序都会停止。4. 常用参数说明screen 有很多强大的选项,下面是一些常用的参数及其解释:启动会话时指定名称你可以为会话指定一个名称,这样可以更容易地管理多个会话:screen -S mysession该命令将启动一个名为 mysession 的会话。列出所有会话查看当前所有的 screen 会话:screen -ls输出类似于:There are screens on: 1234.mysession (Detached) 5678.othersession (Detached) 2 Sockets in /var/run/screens/S-user.连接到特定会话如果你有多个会话,可以通过以下命令连接到指定的会话:screen -r <会话ID>创建会话并执行命令你可以创建一个会话并同时执行命令:screen -S mysession bash -c "your-command"这将在 mysession 会话中执行指定的命令。持久化运行命令你可以通过 -d -m 参数让 screen 在后台运行一个命令:screen -d -m your-command这会在后台启动一个 screen 会话并执行 your-command。进入已分离的会话当会话被分离后,想要重新连接到这个会话可以使用:screen -r mysession5. 配置文件screen 提供了配置文件功能,可以在文件 .screenrc 中指定个性化设置。你可以在用户的主目录下创建这个文件,或者在 /etc/screenrc 中设置系统级别的配置。常见的配置选项包括:设置默认窗口的标题:hardstatus alwayslastline "%{= kG}%-Lw%{= kY}[%n] %t%{-}%+Lw%{= kG}"自动启动某些命令:screen -t mysession bash -c "echo Hello World"6. 高级功能分屏功能screen 允许你在一个窗口中分割出多个视图,类似于 tmux。水平分割:Ctrl+A 然后按 S(split horizontally)垂直分割:Ctrl+A 然后按 |(split vertically)切换分屏:Ctrl+A 然后按 Tab(toggle between splits)关闭分屏:Ctrl+A 然后按 X(close split)设置窗口日志screen 允许你在运行的会话中记录日志,命令如下:Ctrl+A H这会将屏幕内容保存到 screenlog.0 文件中,默认保存在当前目录。7. 退出 screen在 screen 中,退出的方法有两种:在当前会话中使用 exit 命令,或者按下 Ctrl+D 退出 shell 会话;在 screen 内部按下 Ctrl+A 然后按 K,这将关闭当前窗口。如果你已经分离了会话,使用 screen -r 重新连接后也可以通过退出会话关闭会话。
2025年01月13日
7 阅读
0 评论
1 点赞
使用 SSH 端口转发实现内网穿透
SSH 端口转发是一种高效、安全的方式,可以将本地服务暴露到远程服务器,或者将远程服务映射到本地。SSH 端口转发的类型本地端口转发 (-L) 将远程服务器上的服务映射到本地端口,用于访问远程服务。ssh -L [本地地址:本地端口]:[远程地址:远程端口] user@your-server示例:ssh -L 8080:localhost:80 user@your-server本地 8080 端口映射到远程服务器的 80 端口。本地访问 http://localhost:8080,即访问远程服务器的 http://localhost:80。远程端口转发 (-R) 将本地服务映射到远程服务器的端口,用于将本地服务暴露到外网。ssh -R [远程地址:远程端口]:[本地地址:本地端口] user@your-server示例:ssh -R 0.0.0.0:8888:localhost:8080 user@your-server远程服务器的 8888 端口映射到本地的 8080 端口。外部访问 http://your-server:8888,即可访问本地的 http://localhost:8080。动态端口转发 (-D) 将本地端口作为 SOCKS 代理,用于动态访问任意远程服务。ssh -D [本地地址:本地端口] user@your-server示例:ssh -D 127.0.0.1:1080 user@your-server本地 127.0.0.1:1080 作为 SOCKS 代理,可通过浏览器等工具配置访问外网。配置 /etc/ssh/sshd_config 文件为了使远程端口转发(-R)正常工作,可能需要修改远程服务器的 SSH 配置文件 /etc/ssh/sshd_config。关键配置项允许 TCP 转发确保以下配置为 yes:AllowTcpForwarding yes启用网关端口使远程端口可以绑定到非本地地址:GatewayPorts yesGatewayPorts no:默认值,只允许绑定到 127.0.0.1(本地回环地址)。GatewayPorts yes:允许绑定到所有地址。GatewayPorts clientspecified:根据客户端的 -R 命令指定绑定地址。重启 SSH 服务修改配置后,重启 SSH 服务使其生效:sudo systemctl restart sshd常用组合参数1. 保持连接活跃 (-fN)-f:在连接建立后,SSH 会后台运行。-N:只建立端口转发,不执行远程命令。ssh -fN -L 8080:localhost:80 user@your-server2. 指定绑定地址-L 本地绑定地址:127.0.0.1 仅本地访问,0.0.0.0 外部可访问。-R 远程绑定地址:同样使用 127.0.0.1 或 0.0.0.0。ssh -R 0.0.0.0:8888:localhost:8080 user@your-server3. 动态端口转发 + 指定 SOCKS 代理使用 -D 开启动态端口转发,将本地端口作为 SOCKS 代理:ssh -D 127.0.0.1:1080 user@your-server4. 禁用伪终端-T:禁用伪终端分配,用于纯端口转发:ssh -T -R 8888:localhost:8080 user@your-server5. 指定配置文件-F:使用自定义 SSH 配置文件:ssh -F ~/.ssh/custom_config -L 8080:localhost:80 user@your-server远程端口转发的安全性考虑限制绑定地址如果不需要外网访问,建议远程端口绑定到 127.0.0.1,避免暴露服务:ssh -R 127.0.0.1:8888:localhost:8080 user@your-server强制使用 SSH 密钥认证配置服务器强制使用密钥认证,避免账户被暴力破解:PasswordAuthentication no监控转发端口的使用在远程服务器上监控端口转发的使用情况:netstat -tlnp完整案例1. 将本地服务暴露到远程服务器并开放外网访问ssh -R 0.0.0.0:8888:localhost:8080 user@your-server在远程服务器的 8888 端口监听,外部可通过 http://your-server:8888 访问。2. 映射远程服务到本地ssh -L 8080:localhost:80 user@your-server将远程服务器的 80 端口映射到本地 8080,本地访问 http://localhost:8080。3. 配置 SOCKS 代理ssh -D 127.0.0.1:1080 user@your-server本地 127.0.0.1:1080 作为 SOCKS 代理,可代理访问外网。
2025年01月08日
7 阅读
0 评论
2 点赞
2024-12-06
Vue3 快速入门
使用 Vite 快速搭建 Vue 3 项目创建项目:npm create vite@latest my-vue-app --template vue cd my-vue-app npm install npm run dev目录结构:src/: 主代码目录main.js: 应用入口文件Setup 语法糖与响应式对象在 Vue 3 的 <script setup> 中,ref 和 reactive 是核心的响应式 API:ref: 用于定义单个值的响应式数据。<script setup> import { ref } from 'vue'; const count = ref(0); const increment = () => { count.value++; }; </script> <template> <button @click="increment">{{ count }}</button> </template>注意:访问或更新 ref 的值需要通过 .value。reactive: 用于定义复杂对象的响应式数据。<script setup> import { reactive } from 'vue'; const state = reactive({ count: 0, message: 'Hello Vue 3' }); const increment = () => { state.count++; }; </script> <template> <button @click="increment">{{ state.count }} - {{ state.message }}</button> </template>注意:reactive 不需要 .value,直接操作对象属性即可。区别ref 更适合简单的标量值。reactive 更适合复杂的嵌套对象。常用指令条件与循环v-if 和 v-else: 条件渲染。<template> <p v-if="isLoggedIn">欢迎回来!</p> <p v-else>请登录</p> </template>v-show: 控制元素显示。<template> <p v-show="isVisible">这是一条可见信息</p> </template>v-for: 列表渲染。<script setup> const items = [1, 2, 3, 4]; </script> <template> <ul> <li v-for="item in items" :key="item">{{ item }}</li> </ul> </template>事件绑定@click: 点击事件。<template> <button @click="handleClick">点击我</button> </template> <script setup> const handleClick = () => { alert('按钮被点击了!'); }; </script>@input 和 v-model: 双向绑定。<template> <input v-model="text" /> <p>{{ text }}</p> </template> <script setup> import { ref } from 'vue'; const text = ref(''); </script>@mouseenter 和 @mouseleave: 鼠标事件。<template> <div @mouseenter="onHover" @mouseleave="onLeave">悬停我!</div> </template> <script setup> const onHover = () => { console.log('鼠标进入'); }; const onLeave = () => { console.log('鼠标离开'); }; </script>属性绑定v-bind: 动态绑定属性。<template> <img :src="imageUrl" alt="动态图片" /> </template> <script setup> const imageUrl = 'https://example.com/image.jpg'; </script>v-once: 一次性渲染。<template> <p v-once>{{ message }}</p> </template> <script setup> const message = '这段文字只渲染一次'; </script>自定义组件子组件定义一个简单的按钮组件:<script setup> import { defineProps } from 'vue'; defineProps({ label: String }); </script> <template> <button>{{ label }}</button> </template>父组件父组件传递 label 属性:<script setup> import MyButton from './MyButton.vue'; </script> <template> <MyButton label="Click Me" /> </template>父子组件数据传递父传子通过 props 传递数据:<!-- 子组件 --> <script setup> import { defineProps } from 'vue'; defineProps({ message: String }); </script> <template> <p>{{ message }}</p> </template><!-- 父组件 --> <script setup> import ChildComponent from './ChildComponent.vue'; </script> <template> <ChildComponent message="Hello from Parent" /> </template>子传父通过 emit 通知父组件:<!-- 子组件 --> <script setup> import { defineEmits } from 'vue'; const emit = defineEmits(['updateMessage']); const notifyParent = () => { emit('updateMessage', 'Message from Child'); }; </script> <template> <button @click="notifyParent">Notify Parent</button> </template><!-- 父组件 --> <script setup> import ChildComponent from './ChildComponent.vue'; const handleUpdateMessage = (message) => { console.log(message); }; </script> <template> <ChildComponent @updateMessage="handleUpdateMessage" /> </template>
2024年12月06日
17 阅读
0 评论
3 点赞
Flutter 状态管理之 Provider
在 Flutter 开发中,状态管理是一个非常重要的话题。而 Provider 作为 Flutter 社区推荐的状态管理解决方案之一,因其轻量、简单、灵活而备受欢迎。本文将系统地解析 Provider 的基本用法和高级用法,包括 read、watch、consume 和 selector,并通过单个 Model 和多个 Model 的管理案例详细说明。什么是 Provider?Provider 是一个基于 InheritedWidget 的封装,用于高效地管理 Flutter 应用中的状态。它的主要优势包括:简单易用,符合 Dart 语言的惯用写法。支持多层 Widget 树的状态共享。高性能,只会更新需要重建的 Widget。通过 Provider,我们可以方便地实现依赖注入和响应式编程。Provider 的基本用法在使用 Provider 之前,需要先在 pubspec.yaml 文件中添加依赖:dependencies: provider: ^lates以下通过一个简单的计数器示例说明 Provider 的基本用法。单个 Model 的使用创建 Model 类import 'package:flutter/foundation.dart'; class CounterModel with ChangeNotifier { int _count = 0; int get count => _count; void increment() { _count++; notifyListeners(); } }在应用中注册 Providerimport 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'counter_model.dart'; void main() { runApp( ChangeNotifierProvider( create: (_) => CounterModel(), child: MyApp(), ), ); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( home: CounterScreen(), ); } }获取状态和更新 UIclass CounterScreen extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text('Provider 示例')), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Text('当前计数:'), Text( context.watch<CounterModel>().count.toString(), style: Theme.of(context).textTheme.headline4, ), ], ), ), floatingActionButton: FloatingActionButton( onPressed: () => context.read<CounterModel>().increment(), child: Icon(Icons.add), ), ); } }多个 Model 的管理在大型应用中,可能需要管理多个 Model。在这种情况下,可以使用 MultiProvider。定义多个 Modelclass CounterModel with ChangeNotifier { int _count = 0; int get count => _count; void increment() { _count++; notifyListeners(); } } class ThemeModel with ChangeNotifier { bool _isDark = false; bool get isDark => _isDark; void toggleTheme() { _isDark = !_isDark; notifyListeners(); } }注册多个 Providervoid main() { runApp( MultiProvider( providers: [ ChangeNotifierProvider(create: (_) => CounterModel()), ChangeNotifierProvider(create: (_) => ThemeModel()), ], child: MyApp(), ), ); }在不同的 Widget 中使用 Modelclass CounterScreen extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Provider 示例'), actions: [ IconButton( icon: Icon(Icons.brightness_6), onPressed: () => context.read<ThemeModel>().toggleTheme(), ), ], ), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Text('当前计数:'), Text( context.watch<CounterModel>().count.toString(), style: Theme.of(context).textTheme.headline4, ), ], ), ), floatingActionButton: FloatingActionButton( onPressed: () => context.read<CounterModel>().increment(), child: Icon(Icons.add), ), ); } }Provider 中的核心方法1. readread 方法用于访问状态,但不会订阅状态的变化。这意味着调用 read 的 Widget 在状态更新时不会重建。适用场景:需要触发一次性的操作,例如调用方法或事件处理器。FloatingActionButton( onPressed: () => context.read<CounterModel>().increment(), child: Icon(Icons.add), )2. watchwatch 方法会订阅状态的变化。当状态发生变化时,使用 watch 的 Widget 会重新构建。适用场景:需要根据状态动态更新 UI。Text( context.watch<CounterModel>().count.toString(), style: Theme.of(context).textTheme.headline4, )3. consumeConsumer 是 Provider 提供的一个 Widget,能够订阅状态并重建自身及其子树。适用场景:需要精确控制重建的范围,避免不必要的 Widget 重建。Consumer<CounterModel>( builder: (context, counter, child) { return Text( counter.count.toString(), style: Theme.of(context).textTheme.headline4, ); }, )4. selectorSelector 提供了更高效的订阅方式,可以从状态中选择特定字段进行订阅,避免因其他字段变化导致的无效重建。适用场景:状态对象较大且只需要监听其中部分字段时。Selector<CounterModel, int>( selector: (_, counter) => counter.count, builder: (context, count, child) { return Text( count.toString(), style: Theme.of(context).textTheme.headline4, ); }, )性能优化建议使用 Consumer 或 Selector 控制重建范围:避免不必要的父级 Widget 重建。分离逻辑和 UI:将业务逻辑放在模型中,UI 层只负责展示。尽量减少依赖注入的深度:如果可能,使用多层 Provider。
2024年12月06日
11 阅读
0 评论
1 点赞
1
2
...
19