AutoUpdater.NET 是一个开源库,专为 .NET 桌面应用程序设计,支持 Windows Forms 和 WPF 应用。它通过从服务器获取 XML 文件来检测新版本信息,当发现新版本时向用户显示更新对话框。
相对于 ClickOnce,AutoUpdater.NET 的配置更简单一些。
首先通过 NuGet 包管理器安装 Autoupdater.NET.Official,然后在应用程序入口点添加以下代码:
AutoUpdater.Start("http://yourserver.com/path/to/update.xml");
XML 文件结构如下:
<?xml version="1.0" encoding="UTF-8"?>
<item>
<version>2.0.0.0</version> <!--必填:最新版本号-->
<url>http://yourserver.com/path/to/updatefile.zip</url> <!--必填:更新文件下载地址-->
<changelog>http://yourserver.com/path/to/changelog.txt</changelog> <!--可选:更新日志-->
<mandatory>False</mandatory> <!--可选:是否强制更新-->
</item>
Windows Forms 在 Program.cs 文件的 Main() 方法中,WPF 在 App.xaml.cs 的 OnStartup() 中添加:
AutoUpdater.Start("http://yourserver.com/path/to/update.xml");
AutoUpdater.CheckForUpdateEvent += (e) =>
{
if (e.Error != null)
{
MessageBox.Show($"检查版本更新失败:{e.Error.Message}");
}
if (e.IsUpdateAvailable)
{
if (e.Mandatory.Value)
{
// 强制更新
AutoUpdater.DownloadUpdate(e);
}
else
{
// 可选更新
if (MessageBox.Show("发现新版本,是否立即更新?", "更新提示", MessageBoxButtons.YesNo, MessageBoxIcon.Information) == DialogResult.Yes)
{
AutoUpdater.DownloadUpdate(e);
}
}
}
};
这样就能简单实现打开应用时判断是否有更新。具体用法参:GitHub
对于控制台应用程序,AutoUpdater.NET 并不直接支持。可以使用 GeneralUpdate 等轻量级自动更新库。
其它:
若希望通过标准安装流程(如添加到开始菜单),优先选择 ClickOnce,适合长期维护的内部工具。
若追求快速集成和无感更新,AutoUpdater.NET 更灵活。
无论哪种方案,务必对程序进行代码签名(如购买企业证书或生成测试证书),否则系统可能拦截安装。(你要允许来自未知发布者的此应用对你的设备进行更改吗)
可以购买“OV 代码签名”证书或“EV 代码签名”证书,注意:“代码签名证书”与“域名证书”互不通用。

安装 PyPI(包/库/组件):
pip install 包名
如果安装失败,尝试用国内镜像
pip install 包名 -i https://pypi.tuna.tsinghua.edu.cn/simple
如果不想每次都加 -i 参数,可以更改全局配置
pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple
查看所有配置
pip config list
查看 python 文件路径
# Windows 或 Linux 通用
python -c "import sys; print(sys.executable)"
默认路径为:C:\Users\<user name>\AppData\Local\Programs\Python\Python<version>\python.exe
常用组件介绍
包名 | 介绍 |
---|---|
Flask | 一款基于 Python 的轻量级 Web 开发框架 |
Django | 一款基于 Python 的重量级 Web 开发框架 |
Pandas | 一个数据分析包,提供 Series、Time-Series、DataFrame、Panel、Panel4D、PanelND 等数据结构 |
更多

AsNoTracking 设置未追踪查询
var customers = dbContext.Customers.AsNoTracking().ToList();
这对于只读查询非常有用,因为它可以减少内存使用并提高性能,因为它不需要维护实体的更改跟踪信息。
ExecuteDelete 和 ExecuteUpdate 批量操作
context.Logs.Where(c => c.Time < new DateTime(2000, 1, 1)).ExecuteDelete();
从 EF Core 7 开始,ExecuteDelete 和 ExecuteUpdate 是官方原生支持的批量操作方法。直接操作数据库,不需要调用 SaveChanges():不加载实体到内存,减少内存消耗和网络往返。
若需要分页删除和大批量插入,或在高频、大规模场景,推荐使用 Zack.EFCore.Batch:
context.Logs.Where(c => c.Time < new DateTime(2000, 1, 1)).DeleteRangeAsync(batchSize: 1000);
考虑用 Union 代替 OR
// Where 后行数多时(如分页前)用 OR
var q = db.dt_crm__contract.AsNoTracking();
q = q.Where(c => c.dt_crm__customer.SalesmanId == uid || myIns.Contains(c.IndustryId));
// 用于合并的 q1、q2 的行数少时用 Union
var q1 = db.dt_crm__contract.AsNoTracking().Where(c => c.dt_crm__customer.SalesmanId == uid);
var q2 = db.dt_crm__contract.AsNoTracking().Where(c => myIns.Contains(c.IndustryId));
var q = q1.Union(q2);
“ToDictionary + Count”之前先 Select
// 不推荐
var dic = q.GroupBy(c => c.Date)
.ToDictionary(k => k.Key, v => v.Count());
// 推荐
var dic = q.GroupBy(c => c.Date)
.Select(g => new { g.Key, Count = g.Count() })
.ToDictionary(k => k.Key, v => v.Count);

临界区与 lock 关键字
核心作用:
通过将多线程访问串行化,保护共享资源或代码段。lock 关键字是 Monitor 类的语法糖,提供异常安全的临界区实现。
实现示例:
// 创建私有静态只读对象 // private static readonly object _lockObj = new object(); private static readonly System.Threading.Lock _locker = new(); // .NET 9+ 推荐使用 Lock 类型,避免传统 object 的性能损耗 public void ThreadSafeMethod() { lock (_lockObj) { // 临界区代码(每次仅一个线程可进入) } }
超时机制:
高并发场景可结合 Monitor.TryEnter 设置超时,避免无限等待:
if (Monitor.TryEnter(lockObject, TimeSpan.FromSeconds(1))) { try { /* 操作 */ } finally { Monitor.Exit(lockObject); } }
关键特性:
用户态锁(无内核切换开销)
自动调用Monitor.Enter和Monitor.Exit
必须使用专用私有对象作为锁标识
注意事项:
❌ 避免锁定this、Type实例或字符串(易引发死锁)
❌ 避免嵌套锁(需严格按顺序释放)
✅ 推荐readonly修饰锁对象
❌ lock 不适用于异步代码(async/await),需使用 SemaphoreSlim 实现异步锁
互斥锁(Mutex)
核心作用:
系统级内核锁,支持跨进程同步,但性能开销较高(用户态/内核态切换)。
实现示例:
using var mutex = new Mutex(false, "Global\\MyAppMutex"); try { // 等待锁(最大等待时间500ms) if (mutex.WaitOne(500)) { // 临界区代码 } } finally { if (mutex != null) { mutex.ReleaseMutex(); } }
关键特性:
支持跨应用程序域同步
线程终止时自动释放锁
支持命名互斥体(系统全局可见)
适用场景:
单实例应用程序控制
进程间共享文件访问
硬件设备独占访问
信号量(Semaphore)
核心作用:
通过许可计数器控制并发线程数,SemaphoreSlim为轻量级版本(用户态实现)。
实现对比:
类型 跨进程 性能 最大许可数 Semaphore ✔️ 低 系统限制 SemaphoreSlim ❌ 高 Int32.Max 代码示例:
// 创建初始3许可、最大5许可的信号量 var semaphore = new SemaphoreSlim(3, 5); semaphore.Wait(); // 获取许可 try { // 资源访问代码 } finally { semaphore.Release(); }
异步编程
private readonly SemaphoreSlim _asyncLock = new(1, 1); public async Task UpdateAsync() { await _asyncLock.WaitAsync(); try { /* 异步操作 */ } finally { _asyncLock.Release(); } }
典型应用:
数据库连接池(限制最大连接数)
API 请求限流
批量任务并发控制
事件(Event)
核心机制:
通过信号机制实现线程间通知,分为两种类型:
类型 信号重置方式 唤醒线程数 AutoResetEvent 自动 单个 ManualResetEvent 手动 所有 使用示例:
var autoEvent = new AutoResetEvent(false); // 等待线程 Task.Run(() => { autoEvent.WaitOne(); // 收到信号后执行 }); // 信号发送线程 autoEvent.Set(); // 唤醒一个等待线程
高级用法:
配合WaitHandle.WaitAll实现多事件等待
使用ManualResetEventSlim提升性能
读写锁(ReaderWriterLockSlim)
核心优势:
实现读写分离的并发策略,适合读多写少场景(如缓存系统)。
锁模式对比:
模式 并发性 升级支持 读模式(EnterReadLock) 多线程并发读 ❌ 写模式(EnterWriteLock) 独占访问 ❌ 可升级模式 单线程读→写 ✔️ 代码示例:
var rwLock = new ReaderWriterLockSlim(); // 读操作 rwLock.EnterReadLock(); try { // 只读访问 } finally { rwLock.ExitReadLock(); } // 写操作 rwLock.EnterWriteLock(); try { // 排他写入 } finally { rwLock.ExitWriteLock(); }
最佳实践:
优先使用ReaderWriterLockSlim(旧版有死锁风险)
避免长时间持有读锁(可能饿死写线程)
原子操作(Interlocked)
原理:
通过CPU指令实现无锁线程安全操作。
常用方法:
int counter = 0; Interlocked.Increment(ref counter); // 原子递增 Interlocked.Decrement(ref counter); // 原子递减 Interlocked.CompareExchange(ref value, newVal, oldVal); // CAS操作
适用场景:
简单计数器
标志位状态切换
无锁数据结构实现
自旋锁(SpinLock)
核心特点:
通过忙等待(busy-wait)避免上下文切换,适用极短临界区(<1微秒)。
实现示例:
private SpinLock _spinLock = new SpinLock(); public void CriticalOperation() { bool lockTaken = false; try { _spinLock.Enter(ref lockTaken); // 极短临界区代码 } finally { if (lockTaken) _spinLock.Exit(); } }
优化技巧:
单核CPU需调用Thread.SpinWait或Thread.Yield
配合SpinWait结构实现自适应等待
同步机制对比指南
机制 跨进程 开销级别 最佳适用场景 lock ❌ 低 通用临界区保护 Mutex ✔️ 高 进程间资源独占 Semaphore ✔️ 中 并发数限制(跨进程) SemaphoreSlim ❌ 低 并发数限制(进程内) ReaderWriterLockSlim ❌ 中 读多写少场景 SpinLock ❌ 极低 纳秒级临界区 Interlocked - 无锁 简单原子操作
选择原则:
优先考虑用户态锁(lock/SpinLock/SemaphoreSlim)
跨进程需求必须使用内核对象(Mutex/Semaphore)
读写比例超过10:1时考虑读写锁
自旋锁仅用于高频短操作(如链表指针修改)
通过以上结构化的分类和对比,开发者可以更精准地选择适合特定场景的线程同步方案。建议在实际使用中配合性能分析工具(如BenchmarkDotNet)进行量化验证。
💡 ASP.NET 的异步编程(async/await)本质是单进程内的线程调度,不算“跨进程”。每个 IIS 应用程序池对应一个独立的工作进程(w3wp.exe),不同用户访问同一应用程序池下的 ASP.NET 网站,两者的请求均由同一个 w3wp.exe 进程处理。可能跨进程的场景有:Web Garden 配置、多应用程序池部署等。
在 C# 中,除了常规锁机制(如 lock、Mutex、Semaphore 等),还有一些内置类型通过内部锁或无锁设计实现线程安全。以下是常见的几类:
线程安全集合(System.Collections.Concurrent)这些集合通过细粒度锁或无锁算法(如 CAS)实现线程安全,适合高并发场景。
ConcurrentDictionary:分段锁机制,将数据分片存储,每个分片独立加锁,减少锁竞争。
ConcurrentQueue / ConcurrentStack:基于原子操作(Interlocked)保证线程安全。
ConcurrentBag:每个线程维护本地存储,减少争用,适合频繁添加和移除的场景。
BlockingCollection:基于 ConcurrentQueue 和信号量(SemaphoreSlim)实现生产-消费者模式,支持阻塞和超时。
不可变集合(System.Collections.Immutable) 通过数据不可变性实现线程安全(无需锁),每次修改返回新对象。
Lazy 的线程安全初始化(Lazy<T>) 通过锁或 Interlocked 确保延迟初始化的线程安全。
通道(System.Threading.Channels)用于异步生产-消费者模型,内部通过锁和信号量管理容量限制。
内存缓存(System.Runtime.Caching.MemoryCache)内部使用锁保护共享状态,确保线程安全。
原子操作类型(Interlocked 类、Volatile 关键字、Unsafe 类)通过 CPU 指令实现无锁线程安全。
其他同步工具(Barrier、CountdownEvent)虽然不是严格意义上的锁,但用于协调线程。

通常,我们在更新一条数据库记录时,EF 先取出这一条记录:
var log = DbContext.MyTable.Find(id);
然后赋值字段并保存:
log.Result = "OK";
DbContext.SaveChanges();
这样就会产生两次数据库查询。
我们尝试用 Attach 方法。
先创建一个仅包含主键的对象:
var log = new MyTable { Id = id };
将对象附加到上下文:
DbContext.MyTable.Attach(log);
然后更新需要更新的字段:
log.Result = "OK";
DbContext.SaveChanges();
这样,能在保留其它字段值的前提下,减少一次数据库查询。
但是需要注意的是:
当某非 null 字段需要恢复默认值时,EF 会忽略这个更改。(可能会因 EF 版本等原因有不同的结论)
举个例子:
某记录有个 int 型字段 a,在数据库中这个记录的 a 的值为 1,但 C# 中 int 型的默认值为 0,所以当 Attach 附加这个对象后,如果重新设置 log.a 为 0,那么保存后 a 的值仍为 1。
还有一种写法,利用 ExecuteUpdate 方法:
var affectedRows = DbContext.MyTable
.Where(c => c.Id == id)
.ExecuteUpdate(setters => setters
.SetProperty(c => c.Result, "OK")
);
返回匹配的行数。
这种写法不会遇到“恢复为默认值不生效”的问题,推荐使用。

本文记录于 2024 年 11 月。
升级前 | 期望(最新正式版) | 最终选择 | |
操作系统 | Alibaba Cloud Linux 3 | Alibaba Cloud Linux 3 | Alibaba Cloud Linux 3 |
管理面板 | 宝塔面板 Linux 版 9.2.0 | 宝塔面板 Linux 版 9.2.0 | 宝塔面板 Linux 版 9.2.0 |
Web 服务 | nginx 1.24 | nginx 1.24 | nginx 1.24 |
脚本语言 | PHP 7.4 | PHP 8.2 | PHP 8.2 |
数据库 | PolarDB MySQL 5.6 | RDS MySQL 9.1 | PolarDB MySQL 8.0 |
论坛程序 | Discuz! X3.4 GBK | Discuz! X5.0 | Discuz! X3.5 UTF8 |
版本选择原因:
Discuz! X5 刚刚发布,生态尚未成熟,考虑到是老论坛升级,所以选择 X3.5。
Discuz! X3.5 目前最高支持 PHP 8.2、MySQL 8.0。
完整升级步骤:
购买新的 ECS、PolarDB,具体环境配置步骤参此文;
安装宝塔面板并配置;
安装 nginx 及 PHP;
创建网站、配置 SSL、伪静态、防盗链、可写目录禁执行、仅允许部分入口文件执行等(.conf);
配置 hosts;
如果是正式升级阶段,关闭论坛,防止产生新数据。
备份原网站程序、PolarDB 数据库;
PolarDB 创建快照。
测试阶段:从快照还原到新实例(MySQL 5.6 不能直接恢复到 MySQL 8.0),然后从 5.6 迁移到 8.0.x;
正式阶段:全量模式直接从原实例迁移到 8.0.x,若增量模式且存在触发器,建议从快照还原;
上传原网站程序到新的站点目录下;
按 Discuz! X 升级文档升级 X3.4 至 X3.5;详情见下文 ↓;
升级完成后切换到 PHP 8;
配置 OSS、Redis、更新缓存等;
测试论坛基本功能是否正常;检查附件是否能够正常上传;检查附件是否正常显示;全面检查控制台配置;
逐个开启插件并检查兼容性(短信通、马甲引擎等);
按二开备忘录逐个按需进行二开;
逐个修改调用论坛接口的项目及直接调用论坛数据库的项目;
调试 MAGAPP 接口;
尝试强制 https 访问;
将以上所有修改后的程序保留备份;发布升级公告并关闭论坛;重复以上步骤;修改域名解析;开启论坛;
配置 IP 封禁、定时器、日志、自动备份、配置其它 ECS 的 hosts 等;
查看搜索引擎中收录的地址,是否有无法访问的情况;
尝试将历史遗留的本地附件全部转移到 OSS;
建议 在新服上创建 3 个网站:
第 1 个用来尝试迁移、升级、二开,并测试所有功能;
第 2 个用来再次重复这些步骤,最终保留程序代码及 UGC 文件,作为最终的网站程序,以正式域名作为网站根目录路径;
第 3 个用来正式升级,主要功能是升级最新数据库。完成后修改第 2 个网站的数据库连接指向到最新的数据库,差异化同步新增的 UGC 文件到第 2 个网站。
Discuz! X 升级步骤及注意点:
因 PolarDB MySQL 不支持压缩,所以应移除 Discuz! 和 UCenter 代码中所有的 MYSQLI_CLIENT_COMPRESS,将 , MYSQLI_CLIENT_COMPRESS 替换为 /*, MYSQLI_CLIENT_COMPRESS*/。
升级前务必先修改 ./config/ 目录下的数据库/缓存连接信息,以防出现新站连接老库的情况;
按官方文档进行升级,升级前先修改一下:
【UC】先升级 UCenter 1.6 至 1.7。
将 /uc_server/data 权限改为 777 并递归。
打开 update_ucenter_adult.php 修改 $limit 值为 10000 以免执行超时。
因通信失败的“发送通知失败”可以直接改 URL 参数跳过就完成了,原因可能是因数据量大,发送改名通知执行改名时超时。等DZ升级完成后UC会自动重试改名通知,或单独写个 php 文件将 UCenter 的用户名同步到应用的数据库。
【DZ】运行到 /install/update_adult.php?step=innodb&table=pre_common_member_grouppm 时报错:Duplicate key name 'gpmid' ALTER TABLE common_member_grouppm ADD INDEX gpmid(gpmid);
解决方法:先删除索引,因保存时提示失败,应同时取消 gpmid 字段的自增,转换成功后再设置自增。
【DZ】运行到 /install/update_adult.php?step=file 一片空白而停止
正在解决
【问题】common_menber 表用户名字段编码转换失败
原因是部分用户名包含特殊字符(如全角空格),用以下语句查看两个表同一 uid 的不同用户:
SELECT u.uid, u.username AS ucenter_username, c.username AS common_username FROM pre_ucenter_members u JOIN pre_common_member c ON u.uid = c.uid WHERE u.username <> c.username
Discuz! 用户登录都是以 UCenter 中的用户名为主,所以可以写个小程序直接将 pre_ucenter_members 的用户名同步到 pre_common_member 中,另外 pre_ucenter_members 的用户数少于 pre_common_member 是正常的。若 pre_common_member_archive 表遇到错误同理。
如果用户登录慢,或打开 UCenter 慢,是因为 UC 正在通知 DZ 改用户名,每次打开一个页面会更改一个用户名,具体可以查看 pre_ucenter_notelist 中 closed 为 0 的队列,或进入 UC 后台-数据列表-通知列表 查看。
【问题】发布主题遇到错误:(1062) Duplicate entry '*' for key 'pid'
【原因】forum_post 中的 pid 不是自动增长的,而是由表 forum_post_tableid 中自动增长的 pid 生成的。如果生成的 pid 值已在 forum_post 表中存在,则会出现此错误。
【解决】迁移数据库时应关闭论坛,以防止 forum_post 表有新数据插入。
【问题】打开帖子页面 ./thread-***-1-1.html 显示 404 Not Found,而 ./forum.php?mod=viewthread&tid=*** 可以正常打开
【原因】未配置伪静态(可在宝塔面板中选择)
【问题】打开 UCenter 时报错:UCenter info: MySQL Query Error SQL:SELECT value FROM [Table]vars WHERE name='noteexists'
【解决】打开文件 ./uc_server/data/config.inc.php 配置数据库连接
【问题】打开登录 UCenter 后一片空白
【解决】将目录 ./uc_server/data/ 设为可写
需要将原来安装的插件文件移回 ./source/plugin/ 目录,并设置可写;
界面-表情管理,界面-编辑器设置-Discuz!代码
后续 Discuz! X3.5 小版本升级注意事项:
确认插件是否支持新版本(如短信通)
先创建一个新网站测试二开代码
保留 /config/、/data/、/uc_client/data/、/uc_server/data/、/source/plugin/,其它移入 old
上传文件
移回其它需要的文件,如:
-- 勋章/loading/logo/nv 等:/static/image/common/
-- 表情:/static/image/smiley/
-- 水印:/static/image/common/watermark.*
-- 风格:/template/default/style/t2/nv.png 等
-- 默认头像:/uc_server/images/noavatar_***.gif
-- 根目录 favicon.ico 等
-- 及其它非 DZ 文件
再次检查可写目录的写入权限和禁止运行 PHP 效果。

本文基于 manifest v3
插件使用 Web 技术开发
浏览器提供额外的插件 API
插件与网页分离,运行在一个独立的环境中
插件 API 功能
管理 Tabs、窗口、历史记录、书签、Cookies、下载、浏览数据、通知、网站权限
管理浏览器的外观和感觉 - 背景、主题、右键菜单、新标签页、启动页面
定制 DevTools
向网页注入脚本,与网页通信,与系统中的 Native 应用程序通信
修改/监听发送的 HTTP 请求/接收的回复
插件构成
结构 | 功能 | 调用 API | 操作 Dom | 进程 |
manifest | 配置文件 | - | ||
popup | 弹出对话框 | 所有 | Extension process | |
option page | 用户使用的设置页面 | 所有 | ||
background script | 后台脚本 | 所有 | 禁止? | Extension process |
content script | 内容脚本(注入到网页中) | 有限 | 允许 | Renderer process |
* 即便 content script 是注入到网页中的,而且是运行在 Renderer 进程(与主网页相同的进程),但是它们仍运行在不同的世界(world)。主网页运行在 main world,插件的 content script 运行在 isolated world。比如说 main world 中有一个变量,它在 isolated world 中是访问不到的,但是如果修改了 dom,对其它世界是有影响的。
将 Chrome 插件迁移到 Edge
移除 Chrome 独有的 API(如调用 Google 账户)
移动 update_URL 字段(如果是从 Chrome 商店直接下载的包会有这个字段)
改名 Chrome 相关的文字(插件名称、描述文字)
参考文献

本文由 ChatGTP 3.5 提供
在 .NET C# 桌面应用程序中,你可以使用委托和事件来实现在窗体页面处理事务过程中实时更新界面。下面是一个示例,展示了在不同情况下如何更新主界面:
首先,在窗体页面中定义一个委托和一个事件,用于更新界面:
public delegate void UpdateUIHandler(string msg);
public event UpdateUIHandler UpdateUIEvent;
然后,在窗体的构造函数中订阅事件,并在事件处理程序中更新界面:
public Form1()
{
InitializeComponent();
UpdateUIEvent += UpdateUI;
}
private void UpdateUI(string msg)
{
if (InvokeRequired)
{
Invoke(new UpdateUIHandler(UpdateUI), msg);
}
else
{
// 在这里更新界面
label1.Text = msg;
}
}
现在,你可以在窗体页面的任何地方调用 UpdateUIEvent
来触发更新界面的事件。例如,在按钮点击事件中:
private void button1_Click(object sender, EventArgs e)
{
// 处理事务过程中实时更新界面
string msg = "处理事务中...";
UpdateUIEvent?.Invoke(msg);
// 异步调用一个类方法中的方法,并在方法内部实时更新主界面
Task.Run(() =>
{
MyClass myClass = new MyClass();
myClass.LongRunningMethod(UpdateUIEvent);
});
}
在上面的示例中,MyClass
是一个自定义的类,其中的 LongRunningMethod
是一个耗时的方法。在这个方法内部,你可以通过传递 UpdateUIEvent
来实时更新主界面:
public class MyClass
{
public void LongRunningMethod(UpdateUIHandler updateUI)
{
// 处理事务过程中实时更新界面
string msg = "处理事务中...";
updateUI?.Invoke(msg);
// 其他耗时操作...
}
}
通过以上示例,你可以在窗体页面处理事务过程中实时更新界面,并且在异步调用的方法内部也能实时更新主界面。记得在更新界面时使用 Invoke
方法,以确保在主线程上更新界面,避免跨线程访问 UI 的问题。

默认端口带来安全隐患,建议更改为 50000-60000 之间的端口号。
Windows 远程桌面(RDP)(3389)
在 Windows 防火墙中放行新端口:在“入站规则”中找到“Open RDP Port 3389”复制并粘贴该规则,修改端口和名称。
若没有这个规则:新建规则 - 端口 - TCP - 特定本地端口(填写新的端口号)- 允许连接 - 名称
如有其它防火墙或安全组也一并配置(如阿里云 ECS 的安全组)
打开注册表(regedit),展开到:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp,右侧双击“PortNumber”切换到“十进制”,将 3389 改为新端口号
重启生效
在防火墙和安全组中禁止原默认端口
SSH (22) 之 CentOS
从阿里云控制台登录服务器(如果未设置 root 密码则先设置),直接跳到第 4 步
在外部防火墙中放行新的端口号(如阿里云 ECS 的安全组)
在内部防火墙中放行新的端口号(如 firewalld 或 iptables),使用宝塔面板的直接在面板“安全”页面设置即可
打开 SSH 配置文件
sudo vi /etc/ssh/sshd_config
找到并编辑 Port 行的端口号并启用,改为其它端口号
#Port 22
重新加载使生效
sudo systemctl reload sshd
在防火墙和安全组中禁止原默认端口
建议使用 SSH 密钥对代替传统账号密码登录
FTP (21) 之 FileZilla Server Windows 版
一般地,在 Windows Defender 防火墙中是以添加应用 filezilla-server.exe 的方式允许的,所以不需要更改端口。如果以端口方式允许的,那么在入站规则中允许新的端口。
如有其它防火墙或安全组也一并配置(如阿里云 ECS 的安全组)
打开 Administer FileZilla Server,打开菜单 - Server - Configure - Server listeners,右侧窗口中将 Port 改为新端口(强烈建议将 Protocol 改为“Require explicit FTP over TLS”,即禁止 FTP 协议,改为使用 FTPS 协议)
从防火墙和安全组移除 21 端口
FTP (21) 之 Pure-Ftpd(宝塔面板)
在防火墙中放行新的端口号(如阿里云 ECS 的安全组)
进入宝塔面板,打开“安全”,添加端口规则 TCP
在宝塔面板中进入软件商店,找到 Pure-Ftpd 并打开,切换到“配置修改”,搜索“Bind”,删除开头的“#”,将端口号 21 改为新端口号,保存(强烈建议将 TLS 项改为 2,即禁止 FTP 协议,仅允许 FTPS 协议)
切换到“服务”选项卡,点击“重启”
从防火墙和安全组移除 21 端口
MySQL (3306) 之阿里云云数据库 RDS MySQL 版
打开控制台 RDS 实例页,左侧菜单点击“白名单与安全组”,切换到“安全组”查看正在使用的安全组ID
(若使用了安全组)打开控制台 ECS 首页,左侧菜单点击“安全组”,找到这个安全组,放行新的端口
打开控制台 RDS 实例页,左侧菜单点击“数据库连接”,点击“修改连接地址”,在弹出框中修改端口
从防火墙和安全组移除原端口(确保没有其它实例正在使用此端口)
PolarDB (3306)
打开控制台 PolarDB 集群实例页,左侧菜单点击“集群白名单”,切换到“安全组”查看正在使用的安全组ID
(若使用了安全组)打开控制台 ECS 首页,左侧菜单点击“安全组”,找到这个安全组,放行新的端口
打开控制台 PolarDB 集群实例页,左侧菜单点击“基本信息”,点击“主地址”和“集群地址”的“配置”,在“网线信息”中点击“更多”更改端口
从防火墙和安全组移除原端口(确保没有其它实例正在使用此端口)
MSSQL (1433) 之阿里云云数据库 RDS SQL Server 版
打开控制台 RDS 实例页,左侧菜单点击“白名单与安全组”,切换到“安全组”查看正在使用的安全组ID
(若使用了安全组)打开控制台 ECS 首页,左侧菜单点击“安全组”,找到这个安全组,放行新的端口
打开控制台 RDS 实例页,左侧菜单点击“数据库连接”,点击“修改连接地址”,在弹出框中修改端口
从防火墙和安全组移除原端口(确保没有其它实例正在使用此端口)
Redis (6379) 之阿里云云数据库 Redis 版
打开控制台 Redis 实例页,左侧菜单点击“白名单设置”,切换到“安全组”查看正在使用的安全组ID
(若使用了安全组)打开控制台 ECS 首页,左侧菜单点击“安全组”,找到这个安全组,放行新的端口
打开控制台 Redis 实例页,在“连接信息”中点击“修改连接地址”,在弹出框中修改端口
从防火墙和安全组移除原端口(确保没有其它实例正在使用此端口)
宝塔面板 (8888)
在防火墙中放行新的端口号(如阿里云 ECS 的安全组),或直接在私网其它 ECS 上的浏览器上直接访问原 8888 端口的地址
进入宝塔面板,打开面板设置,切换到“安全设置”页,找到“面板端口”,点击“设置”
在防火墙和安全组中禁止原默认端口
IIS 管理服务(Web 部署)(8172)
在 Windows 防火墙中放行新端口:在“入站规则”中找到“Web 管理服务(HTTP 流量入站)”因其为预定义规则且复制也无法修改,所以按其设置新建一个,并指定新的端口。
如有其它防火墙或安全组也一并配置(如阿里云 ECS 的安全组)
打开 IIS 管理器 - 管理服务,右侧停止,左侧修改端口,右侧应用、启动
VS 中发布配置修改“服务器(E)”项添加端口(域名:端口),第一次连接接受证书
在防火墙和安全组中禁止原默认端口

本文图片基于网络图片更新,如有侵权,请通过网站底部联系站长删除。
本文内容来源于网络,如有错误欢迎批评指正。
USB 接口类型
USB 接口有 Mini、Micro、Type 三种外观。
通常说的 USB-C 一般指 USB Type-C,因为没有 Mini-C 和 Micro-C。而 USB-A / USB-B 一般也特指 Type-A / Type-B。
数据传输能力
USB 标准(附 Thunderbolt)
规格 | 别名 | 接口类型 | 理论带宽 | 电力规格 | 备注 |
USB 1.0 | Low-Speed | Mini A / B Micro A / B 2.0 Type A / B 2.0 | 1.5 Mbps | 5V/0.5A | |
USB 1.1 | Full-Speed | 12 Mbps | 5V/0.5A | ||
USB 2.0 | Hi-Speed High Speed | Mini A / B Micro A / B 2.0 Type A 2.0 / B 2.0 / C | 480 Mbps | 5V/0.5A | |
USB 3.0 USB 3.1 Gen 1 USB 3.2 Gen 1 | SuperSpeed | Micro B 3.0 Type A 3.x / B 3.x / C | 5 Gbps | 5V/0.9A PD2.0 100W | |
USB 3.1 USB 3.1 Gen 2 USB 3.2 Gen 2 | SuperSpeed+ | Micro B 3.0 Type A 3.x / B 3.x / C | 10 Gbps | 5V/0.9A PD2.0 100W | |
USB 3.2 USB 3.2 Gen 2×2 | SuperSpeed 20Gbps | Type-C | 20 Gbps | PD2.0 100W | |
USB4 Gen 2×2 | USB4 20Gbps | Type-C | 20 Gbps | PD3.0 100W PD3.1 240W | 兼容 Thunderbolt 3 |
USB4 Gen 3×2 | USB4 40Gbps | Type-C | 40 Gbps | ||
USB4 2.0 | USB4 80Gbps | Type-C | 80 Gbps | ||
Thunderbolt 1 | 雷雳1、雷电1 | Mini DisplayPort | 10 Gbps | ||
Thunderbolt 2 | 雷雳2、雷电2 | Mini DisplayPort | 20 Gbps | ||
Thunderbolt 3 | 雷雳3、雷电3 | Type-C | 40 Gbps | 配件供电 15W PD 100W | 兼容 USB4 |
Thunderbolt 4 | 雷雳4、雷电4 | Type-C | 40 Gbps | 配件供电 15W PD 100W | 兼容 Thunderbolt 3 |
Thunderbolt 5 | 雷雳5、雷电5 | Type-C | 80Gpb (带宽增强 120Gpbs) | 240W | USB4 V2、DisplayPort 2.1 和 PCI Express Gen 4 |
Thunderbolt / 雷雳 / 雷电 是同一个意思,而闪电接口指的是 Lightning,都是区别于 USB 的传输技术
Thunderbolt 本身是数据传输和显示协议,Thunderbolt 3 起采用 USB-C 外观,支持 PD 协议后可进行快速充电
识别不同标准的接口,比如若 Type-C 接口旁边写着 ss 和 5 表示 SuperSpeed 和 5Gbps,即 USB 3.0;插口旁边带有⚡️标志表示雷电接口。
电力传输能力
常见快充协议
协议 | 版本 | 发布年份 | 区别 | 接口形态 |
BC (Battery Charging Specification) | 1.2 | 2010 年 | 7.5W(5V/1.5A) | |
高通 QC (Qualcomm Quick Charge) | 1.0 | 2013 年 | 10W(5V/2A) | Micro-USB |
2.0 | 2014 年 | Class A:5V、9V、12V 电压可选,最大输出功率为 18W? Class B:5V、9V、12V、20V 电压可选,最大输出功率为 60W | Micro-USB / Type-A | |
3.0 | 2015 年 | Class A:3.6-12V,Class B:3.6-20V,支持动态调整电压和电流,最大输出功率为 18W? | Micro-USB / Type-A / Type-C | |
4.0 | 2017 年 | 5V/5.6A 或 9V/3A,最大输出功率为 28W?,兼容了 USB PD 2.0 / PD 3.0 PPS? | Type-C | |
4+ | 2019 年 | 最大输出功率为 100W?,支持 PPS 协议?兼容 QC2.0~QC3.0 | Type-C | |
5.0 | 2020 年 | 最大输出功率 > 100W,兼容 QC2.0~QC4+ | Type-C | |
USB-PD (USB Power Delivery) | 1.0 | 2012 年 | 5V、12V、20V 电压可选,最大输出功率为 10W | Micro-USB / Type-A / Type-B |
2.0 | 2014 年 | 5V3A、9V3A、15V3A、20V3A、20V5A(E-Marked),最大输出功率为 100W | Type-C | |
3.0 | 2015 年 | 5V3A、9V3A、15V3A、20V3A、20V5A(E-Marked),最大输出功率为 100W | Type-C | |
3.0 PPS | 2017 年 | 支持 PPS 协议,3.3V-21V 3A-5A | Type-C | |
3.1 | 2021 年 | Type-C | ||
3.2 | 2023年 | 强制 AVS,优化 EPR | Type-C |
华为 SuperCharge(FCP / SCP)、小米 Mi Turbo Charge、OPPO VOOC、vivo FlashCharge、三星 AFC 等私有协议不在此列出。
Magsafe 电源适配器 是磁吸式有线充电接口,最大输出功率为 85W(截止2023年),用于 Macbook;
Magsafe 充电器 是磁吸式无线充电接口,最大输出功率为 15W(截止2023年),用于 iPhone,不属于快充。
Qi 是无线充电协议,Qi1 最大输出功率为 7.5W,Qi2 最大输出功率为 15W。
功率决定充电速度,功率与电压电流的关系:P=U*I,如 5V1A=5W
一条 USB 线由插座/母口(Receptacle)、插头/公口(Plug)和线缆(Cable)三部分组成,要实现某个协议,需要插座和插头都支持该协议。
PPS:Programmable Power Supply 可编程电源
SPR:Standard Power Range 标准功率范围
EPR:Extended Power Range 扩展功率范围
FCP:Fast Charge Protocol 华为早期快充协议,支持 18W
SCP:Super Charge Protocol 华为超级快充协议,支持 22.5W、40W
