<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:atom="http://www.w3.org/2005/Atom"
>
<channel>
<title><![CDATA[PicoServer 轻量Web能力胶水库官方文档教程]]></title> 
<atom:link href="https://docs.picoserver.cn/rss.php" rel="self" type="application/rss+xml" />
<description><![CDATA[PicoServer 是一款 .NET 生态的轻量级 Web 能力胶水库，主打 “集成至上、灵活嵌入”。无需依赖 IIS、Kestrel 这类传统 Web 服务器，可直接嵌入任意 .NET 应用快速搭建 Web API；开箱即用零配置，无需修改原有业务代码，无论是轻量级 Web API、WebSocket 实时通信、边缘计算 Web 服务，还是轻量流媒体服务器，用它都恰到好处。]]></description>
<link>https://docs.picoserver.cn/</link>
<language>zh-cn</language>

<item>
    <title>[C#] 零依赖高性能跨平台 Web 胶水库 PicoServer 价值挖掘与选型推荐</title>
    <link>https://docs.picoserver.cn/blog/23.html</link>
    <description><![CDATA[<p><img src="https://docs.picoserver.cn/content/uploadfile/202604/80941777471934.png" alt="" /></p>
<blockquote>
<p><a href="https://picoserver.cn/" title="PicoServer">PicoServer</a> 是 .NET 生态的轻量级 Web 能力胶水库。零依赖，无需 IIS 或 Kestrel，涵盖 Web API、WebSocket 实时通信、Web 站点构建/静态文件托管等功能场景。零配置，一行代码实现 WebAPI ，不绑架业务。既能轻松扩展现有程序，也能基于它开发独立应用。</p>
</blockquote>
<p><strong><a href="https://docs.picoserver.cn/" title="PicoServer官方文档">PicoServer官方文档</a></strong> 有 C# 与 VB.NET 完整使用示例、集成案例、以及<strong><a href="https://docs.picoserver.cn/benchmark.html" title="基于日常开发环境的性能测试报告">基于日常开发环境的性能测试报告</a></strong>，而非特定优化条件下的极限数据。</p>
<h2>一、产品核心定位</h2>
<p>PicoServer 是一款基于 .NET Standard 2.0 构建的 <strong>轻量级高性能跨平台 Web 能力胶水库</strong>。</p>
<p><strong>核心概念</strong>：<code>.NET 应用 + PicoServer = 拥有 Web 能力的应用</code></p>
<p><strong>核心主张</strong>：<strong>库适应业务，而非业务适应框架</strong></p>
<p><strong>兼容定位</strong>：<strong>包容过去，更面向未来。</strong></p>
<h2>二、设计哲学：简单好用</h2>
<p>开发 PicoServer 的原始动机——给自己做项目开发 WebAPI 用。这种“实用架构”的本能，产出了五项核心原则：</p>
<table>
<thead>
<tr>
<th>原则</th>
<th>内涵</th>
<th>工程体现</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>极简路径</strong></td>
<td>从网络请求到业务方法，路径最短</td>
<td>监听→路由→方法，三跳直达</td>
</tr>
<tr>
<td><strong>零侵入集成</strong></td>
<td>不绑架架构，不强制规范</td>
<td>单 DLL（~50 KB），几行代码嵌入</td>
</tr>
<tr>
<td><strong>开箱即用</strong></td>
<td>拿来就干，无需理解整个体系</td>
<td>无 Builder 模式，一个方法激活一个能力</td>
</tr>
<tr>
<td><strong>默认安全</strong></td>
<td>不配错也安全</td>
<td>防目录遍历、隐藏文件保护、JWT 自动验过期</td>
</tr>
<tr>
<td><strong>全异步架构</strong></td>
<td>从第一行代码即为 async/await</td>
<td>无阻塞线程，天然匹配 io_uring、异步 V2</td>
</tr>
</tbody>
</table>
<h3><strong>一行代码实现WebAPI</strong></h3>
<pre><code class="language-csharp">var app = new WebAPIServer();
app.MapGet("/", (req, rsp) =&gt; rsp.WriteAsync("Hello PicoServer"));
app.StartServer();</code></pre>
<h2>三、核心技术能力</h2>
<h3>3.1 “三板斧”核心模块</h3>
<table>
<thead>
<tr>
<th>模块</th>
<th>功能</th>
<th>关键特性</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>路由映射</strong></td>
<td>业务入口层</td>
<td>精准/通配符/RESTful/语义化/特性路由</td>
</tr>
<tr>
<td><strong>中间件扩展</strong></td>
<td>前置控制层</td>
<td><code>AddMiddleware</code> 完全开放，按需注册，无隐式中间件</td>
</tr>
<tr>
<td><strong>内置安全</strong></td>
<td>基础保障层</td>
<td>Token/JWT/国密 SM3 鉴权、防目录遍历、Cookie HttpOnly</td>
</tr>
</tbody>
</table>
<h3>3.2 全场景能力矩阵</h3>
<p><strong>同一端口、同一进程，同时提供三种基础 Web 能力：</strong></p>
<ul>
<li><strong>WebAPI</strong>：全 HTTP 方法、参数自动解析、JSON/表单/流式响应</li>
<li><strong>WebSocket</strong>：双向通信、心跳检测、连接数管控、广播/定向推送</li>
<li><strong>静态文件托管</strong>：缓存策略、MIME 识别、跨域配置、SPA 支持</li>
</ul>
<p><strong>更多能力</strong>：SSE 服务端推送、大文件流式上传下载（断点续传）、流媒体直播推送、库内置 WebSocket 服务端/客户端</p>
<h3>3.3 双语言平权</h3>
<p>C# 与 VB.NET 均提供从基础路由到高级中间件的 <a href="https://docs.picoserver.cn/" title="完整文档与示例代码">完整文档与示例代码</a></p>
<h2>四、性能矩阵</h2>
<h3>4.1 实测数据（笔记本电池供电、平衡模式、零调优）</h3>
<table>
<thead>
<tr>
<th>测试场景</th>
<th>并发</th>
<th>QPS</th>
<th>P99 延迟</th>
<th>错误率</th>
</tr>
</thead>
<tbody>
<tr>
<td>短连接压力</td>
<td>100</td>
<td><strong>55,117</strong></td>
<td>5.3ms</td>
<td>0%</td>
</tr>
<tr>
<td>短连接稳定</td>
<td>50/15s</td>
<td><strong>69,487</strong></td>
<td>1.9ms</td>
<td>0%</td>
</tr>
<tr>
<td>WebSocket 长连接</td>
<td>10,000</td>
<td>服务端 398MB / 客户端 172MB</td>
<td>无卡顿</td>
<td>0 丢失</td>
</tr>
</tbody>
</table>
<h3>4.2 多环境性能画像</h3>
<table>
<thead>
<tr>
<th>部署场景</th>
<th>条件</th>
<th>QPS</th>
</tr>
</thead>
<tbody>
<tr>
<td>Linux 云服务器 2+2</td>
<td>Debian 12/.NET 10/零调优</td>
<td><strong>~2 万</strong></td>
</tr>
<tr>
<td>i3 10 代入门电脑</td>
<td>Windows 10/.NET 10/零调优</td>
<td><strong>~1.8 万</strong></td>
</tr>
</tbody>
</table>
<h3>4.3 资源效率对比</h3>
<table>
<thead>
<tr>
<th>维度</th>
<th>PicoServer</th>
<th>ASP.NET Core</th>
</tr>
</thead>
<tbody>
<tr>
<td>控制测试程序内存</td>
<td><strong>~16 MB</strong></td>
<td>~100 MB+</td>
</tr>
<tr>
<td>交付体积</td>
<td><strong>几十 KB</strong></td>
<td>百 MB 级运行时</td>
</tr>
<tr>
<td>.NET FX 兼容</td>
<td><strong>4.6.1+</strong></td>
<td>不支持</td>
</tr>
<tr>
<td>框架内核开销</td>
<td><strong>几乎为零</strong></td>
<td>宿主/DI/管道/端点/元数据</td>
</tr>
</tbody>
</table>
<h3>4.4 测试方法论独特性</h3>
<p>PicoServer 是同类产品中<strong>公开完整性能测试数据</strong>的项目：</p>
<ul>
<li>测试环境：开发笔记本、电池供电、平衡模式</li>
<li>测试状态：开箱即用、零调优</li>
<li>数据可复现：任何开发者用同样硬件可复现类似结果</li>
</ul>
<p>性能基准——<strong>“开发者基准”</strong>，与传统的“工业基准”（服务器硬件+专家调优+数据中心）形成互补。</p>
<h2>五、.NET 生态的补位</h2>
<p>PicoServer 是 .NET 生态中<strong>唯一同时满足以下所有条件</strong>的 Web 能力产品：</p>
<ol>
<li>基于 .NET Standard 2.0，兼容 .NET Framework 4.6.1+ 至 .NET 10/11 + 全系列</li>
<li>单 DLL 几十 KB、零第三方依赖、零侵入集成</li>
<li>同时具备 WebAPI + WebSocket + 静态文件托管，同端口同进程</li>
<li>全异步架构，支持 AOT</li>
<li>持续迭代维护，拥有国家计算机软件著作权，可免费商用</li>
<li>原生支持国密 SM3 算法，适配信创全栈</li>
<li>C# / VB.NET 双语言完整支持</li>
<li>公开可验证的“<strong><a href="https://docs.picoserver.cn/benchmark.html" title="开发者基准">开发者基准</a></strong>”性能数据</li>
</ol>
<h2>六、性能红利</h2>
<p>PicoServer <strong>站在巨人肩膀上</strong>，超薄架构，不堆叠：</p>
<ul>
<li><strong>极短路径</strong>：监听→路由→方法，三跳直达</li>
<li><strong>无隐式中间件</strong>：PicoServer不为每个请求预设任何内置中间件，按需添加</li>
<li><strong>无包装对象</strong>：直接操作 <code>HttpListenerRequest/Response</code>，零额外分配</li>
<li><strong>全异步 IO</strong>：无阻塞线程，天然匹配 io_uring 和异步 V2，把系统资源留给业务</li>
<li><strong>过去和未来</strong>：既包容过去<code>Framework</code>更拥抱未来<code>.NET</code>。不改代码，自动享受性能红利</li>
</ul>
<p>因为框架层没有堆积冗余抽象，JIT 优化、io_uring、异步 V2 等运行时红利能被更完整地转化为实际吞吐提升。</p>
<h2>七、最佳适配场景</h2>
<table>
<thead>
<tr>
<th>场景</th>
<th>推荐度</th>
<th>核心价值</th>
</tr>
</thead>
<tbody>
<tr>
<td>.NET 存量系统 Web 化改造</td>
<td>★★★★★</td>
<td>零侵入、不改原有代码、C# / VB.NET 支持</td>
</tr>
<tr>
<td>工业自动化/边缘计算</td>
<td>★★★★★</td>
<td>极低 CPU 和内存、WebAPI、WebSocket、Web网页托管，可用于嵌入式 Linux</td>
</tr>
<tr>
<td>桌面应用 Web 化嵌入</td>
<td>★★★★★</td>
<td>单 DLL 嵌入、MAUI 有 MVP 实践</td>
</tr>
<tr>
<td>国产化信创适配</td>
<td>★★★★★</td>
<td>国密 SM3 签名、密码储存、著作权合规</td>
</tr>
<tr>
<td>企业内网轻量服务</td>
<td>★★★★★</td>
<td>单 exe 部署、零运维成本</td>
</tr>
<tr>
<td>新项目快速原型</td>
<td>★★★★★</td>
<td>极简起步，不绑死用户，支持平滑迁移至 ASP.NET Core</td>
</tr>
<tr>
<td>云原生轻量服务</td>
<td>★★★★★</td>
<td>支持 AOT 毫秒级启动、高密度部署、多实例</td>
</tr>
</tbody>
</table>
<h2>八、总结</h2>
<p><strong><a href="https://picoserver.cn/" title="PicoServer">PicoServer</a></strong> 根植于一个朴素的起点：<strong>为了做项目</strong>。不需要的不加、会添乱的不做、让自己慢的不留。PicoServer 架构极简但性能强劲、功能收敛，做功能不做业务，但通过内置和自定义中间件扩展无限可能。</p>
<p>它不与 ASP.NET Core 争夺“全栈框架”的地位，而是补位 .NET 生态中被长期忽视的空白：<strong>让存量系统开口说话，让新项目轻装上路，让任何 .NET 应用都能成为自己的 Web 服务器。</strong></p>
<p>它的性能上限，随 .NET 运行时的每一次进化而自然增长——这不是刻意追求，而是极简架构的自然馈赠。</p>
<blockquote>
<p><strong>包容过去，更面向未来。</strong><br />
Web 连接万物“PicoServer 负责连接，你负责创造”</p>
</blockquote>
<p>PicoServer 官网: <a href="https://picoserver.cn">https://picoserver.cn</a><br />
PicoServer 文档: <a href="https://docs.picoserver.cn">https://docs.picoserver.cn</a><br />
PicoServer C# 示例：<a href="https://docs.picoserver.cn/usage-csharp.html">https://docs.picoserver.cn/usage-csharp.html</a><br />
PicoServer VB.NET 示例：<a href="https://docs.picoserver.cn/usage-vbnet.html">https://docs.picoserver.cn/usage-vbnet.html</a><br />
PicoServer MAUI 系列教程: <a href="https://www.cnblogs.com/densen2014/p/19670899">https://www.cnblogs.com/densen2014/p/19670899</a><br />
PicoServer <strong>开发者基准</strong>测试： <a href="https://docs.picoserver.cn/benchmark.html">https://docs.picoserver.cn/benchmark.html</a></p>]]></description>
    <pubDate>Wed, 29 Apr 2026 22:09:44 +0800</pubDate>
    <dc:creator>PicoServer</dc:creator>
    <guid>https://docs.picoserver.cn/blog/23.html</guid>
</item>
<item>
    <title>【集成示例】PicoServer 与日志（Serilog）集成：轻量服务日志优雅记录</title>
    <link>https://docs.picoserver.cn/blog/22.html</link>
    <description><![CDATA[<p><strong>核心目标</strong>：快速集成日志组件，记录服务运行状态与请求信息，便于问题排查。</p>
<h2>核心准备</h2>
<p>安装所需 NuGet 包：</p>
<pre><code class="language-bash">Install-Package PicoServer
Install-Package Serilog
Install-Package Serilog.Sinks.Console</code></pre>
<h2>C# 极简代码示例</h2>
<pre><code class="language-csharp">using PicoServer;
using Serilog;
using System;

class Program
{
    static void Main(string[] args)
    {
        // 1. 初始化Serilog日志（控制台输出）
        Log.Logger = new LoggerConfiguration()
            .WriteTo.Console()
            .CreateLogger();

        // 2. 启动PicoServer
        var MyAPI = new WebAPIServer();
        MyAPI.StartServer();
        Log.Information("PicoServer启动成功，地址：http://localhost:8090");

        // 3. 注册路由（日志记录请求）
        MyAPI.AddRoute("/", () =&gt; 
        {
            Log.Information("收到根路径请求");
            return "请求成功！日志已记录";
        }, "GET");

        Console.ReadKey();
        Log.Information("服务停止");
        MyAPI.StopServer();
        Log.CloseAndFlush();
    }
}</code></pre>
<h2>VB.NET 极简代码示例</h2>
<pre><code class="language-vb">Imports PicoServer
Imports Serilog
Imports System

Module Program
    Sub Main(args As String())
        ' 1. 初始化Serilog日志（控制台输出）
        Log.Logger = New LoggerConfiguration() _
            .WriteTo.Console() _
            .CreateLogger()

        ' 2. 启动PicoServer
        Dim MyAPI = New WebAPIServer()
        MyAPI.StartServer()
        Log.Information("PicoServer启动成功，地址：http://localhost:8090")

        ' 3. 注册路由（日志记录请求）
        MyAPI.AddRoute("/", Function()
                                 Log.Information("收到根路径请求")
                                 Return "请求成功！日志已记录"
                             End Function, "GET")

        Console.ReadKey()
        Log.Information("服务停止")
        MyAPI.StopServer()
        Log.CloseAndFlush()
    End Sub
End Module</code></pre>
<h2>关键说明</h2>
<ol>
<li>可扩展添加文件日志：安装 <code>Serilog.Sinks.File</code> 包后，可在日志配置中添加 <code>.WriteTo.File("logs/log-.txt", rollingInterval: RollingInterval.Day)</code> 实现按日滚动的文件日志；</li>
<li>两个版本代码功能完全一致，VB.NET 中需使用 <code>_</code> 进行代码换行拼接，Lambda 表达式使用 <code>Function()</code> 语法；</li>
<li>服务停止时需调用 <code>Log.CloseAndFlush()</code> 确保所有日志都被写入，避免日志丢失；</li>
</ol>]]></description>
    <pubDate>Tue, 27 Jan 2026 10:11:33 +0800</pubDate>
    <dc:creator>PicoServer</dc:creator>
    <guid>https://docs.picoserver.cn/blog/22.html</guid>
</item>
<item>
    <title>【集成示例】PicoServer 与依赖注入（DI）集成：轻量服务也能优雅解耦</title>
    <link>https://docs.picoserver.cn/blog/21.html</link>
    <description><![CDATA[<p>本文是PicoServer结合依赖注入（DI）的极简入门示例，核心目标：快速实现接口开发，同时降低代码耦合，适合快速上手。</p>
<h2>一、核心准备</h2>
<h3>1. 安装NuGet包</h3>
<pre><code class="language-bash">Install-Package PicoServer
Install-Package Microsoft.Extensions.DependencyInjection</code></pre>
<h3>2. 核心概念（极简版）</h3>
<ul>
<li>PicoServer：轻量Web请求胶水库，几行代码启动接口服务</li>
<li>DI：依赖注入，由容器管理对象，不用手动new，降低耦合</li>
</ul>
<h2>二、完整入门代码</h2>
<p>示例功能：启动PicoServer，访问根路径/，返回问候语（逻辑由DI注入的服务提供）</p>
<h3>C# 版本</h3>
<pre><code class="language-csharp">using PicoServer;
using Microsoft.Extensions.DependencyInjection;
using System;

// 1. 定义业务服务（接口+实现）
public interface IHelloService
{
    string GetGreeting();
}

public class HelloService : IHelloService
{
    public string GetGreeting()
    {
        return $"Hello PicoServer+DI! Time: {DateTime.Now:HH:mm:ss}";
    }
}

class Program
{
    // 全局DI容器
    private static IServiceProvider _serviceProvider;

    static void Main(string[] args)
    {
        // 2. 构建DI容器并注册服务
        var services = new ServiceCollection();
        // 注册服务（Scoped：每个请求作用域内单例）
        services.AddScoped&lt;IHelloService, HelloService&gt;();
        _serviceProvider = services.BuildServiceProvider();

        // 3. 初始化并启动PicoServer（默认端口8090）
        var MyAPI = new WebAPIServer(); // 变量名改为MyAPI
        MyAPI.StartServer(); // 改为MyAPI.StartServer
        Console.WriteLine("服务启动：http://localhost:8090");

        // 4. 注册路由（从DI容器获取服务）
        MyAPI.AddRoute("/", () =&gt; // 改为MyAPI.AddRoute
        {
            var service = _serviceProvider.GetRequiredService&lt;IHelloService&gt;();
            return service.GetGreeting();
        }, "GET");

        Console.ReadKey();
        // 5. 停止服务+释放资源
        MyAPI.StopServer(); // 改为MyAPI.StopServer
        (_serviceProvider as IDisposable)?.Dispose();
    }
}</code></pre>
<h3>VB.NET 版本</h3>
<pre><code class="language-vb">Imports PicoServer
Imports Microsoft.Extensions.DependencyInjection
Imports System

' 1. 定义业务服务（接口+实现）
Public Interface IHelloService
    Function GetGreeting() As String
End Interface

Public Class HelloService
    Implements IHelloService

    Public Function GetGreeting() As String Implements IHelloService.GetGreeting
        Return $"Hello PicoServer+DI! Time: {DateTime.Now:HH:mm:ss}"
    End Function
End Class

Module Program
    ' 全局DI容器
    Private Shared _serviceProvider As IServiceProvider

    Sub Main(args As String())
        ' 2. 构建DI容器并注册服务
        Dim services = New ServiceCollection()
        ' 注册服务（Scoped：每个请求作用域内单例）
        services.AddScoped(Of IHelloService, HelloService)()
        _serviceProvider = services.BuildServiceProvider()

        ' 3. 初始化并启动PicoServer（默认端口8090）
        Dim MyAPI = New WebAPIServer() ' 变量名改为MyAPI
        MyAPI.StartServer() ' 改为MyAPI.StartServer
        Console.WriteLine("服务启动：http://localhost:8090")

        ' 4. 注册路由（从DI容器获取服务）
        MyAPI.AddRoute("/", Function() ' 改为MyAPI.AddRoute
Dim service = _serviceProvider.GetRequiredService(Of IHelloService)()
                             Return service.GetGreeting()
                         End Function, "GET")

        Console.ReadKey()
        ' 5. 停止服务+释放资源
        MyAPI.StopServer() ' 改为MyAPI.StopServer
        TryCast(_serviceProvider, IDisposable)?.Dispose()
    End Sub
End Module</code></pre>
<h2>三、运行测试</h2>
<ol>
<li>启动程序，打开浏览器访问：<a href="http://localhost:8090">http://localhost:8090</a></li>
<li>页面将显示：Hello PicoServer+DI! Time: 16:30:20（时间实时更新）</li>
</ol>
<h2>四、关键注意事项（新手必看）</h2>
<ol>
<li>端口占用：若8090被占用，启动时指定端口：
<ul>
<li>C#：<code>MyAPI.StartServer(8091);</code></li>
<li>VB.NET：<code>MyAPI.StartServer(8091)</code></li>
</ul></li>
<li>权限被拒绝：Windows下管理员权限运行；</li>
<li>服务解析：<code>GetRequiredService&lt;T&gt;()</code> 若服务未注册会抛异常，确保注册正确；</li>
<li>生命周期：入门用<code>AddScoped</code>即可，简单场景也可换<code>AddTransient</code>（每次新建）；</li>
</ol>]]></description>
    <pubDate>Tue, 27 Jan 2026 10:00:19 +0800</pubDate>
    <dc:creator>PicoServer</dc:creator>
    <guid>https://docs.picoserver.cn/blog/21.html</guid>
</item>
<item>
    <title>为什么开发PicoServer？</title>
    <link>https://docs.picoserver.cn/blog/20.html</link>
    <description><![CDATA[<h1>PicoServer 产品说明</h1>
<h2>一、产品定位</h2>
<p>PicoServer 并非传统意义上的“框架”或“大而全的 Web 解决方案”，其核心定位是：<strong>一个轻量、可嵌入、零配置的 Web 能力胶水库</strong>。</p>
<p><strong>核心目标</strong>：让任何 .NET 程序无需依赖 IIS、Kestrel，也无需改变项目结构，即可快速获得 Web API、WebSocket、静态文件、文件上传、流媒体等核心 Web 能力。</p>
<p><strong>核心优势</strong>：单 DLL 封装、跨平台兼容、免费可商用、稳定可靠，专注服务桌面程序、工控设备、物联网网关、小型服务、快速原型等轻量 Web 场景。</p>
<h2>二、核心能力清单</h2>
<p>PicoServer 已具备完整的轻量 Web 场景能力，满足大多数项目需求：</p>
<ul>
<li>Web API 开发支持</li>
<li>WebSocket 实时通信</li>
<li>静态文件服务部署</li>
<li>跨域请求处理</li>
<li>JWT 身份认证</li>
<li>带进度的文件上传</li>
<li>流媒体/视频播放</li>
<li>长连接推送服务</li>
<li>路由通配符匹配</li>
<li>中间件扩展机制</li>
<li>AOT 编译兼容</li>
<li>全平台运行支持（Windows、Linux、macOS 等）</li>
</ul>
<h2>三、性能表现</h2>
<p>在普通笔记本硬件环境下，PicoServer 性能指标如下，完全满足轻量场景需求：</p>
<ul>
<li>并发处理能力：QPS 5.5 万～7 万</li>
<li>延迟表现：P99 延迟 1.9ms</li>
<li>稳定性：零错误率运行</li>
<li>资源占用：极低 CPU/内存消耗</li>
</ul>
<p><strong>注</strong>：PicoServer 并非为“百万级并发”设计，核心适配桌面、工控、设备、小型服务等轻量场景。</p>
<h2>四、商用授权说明</h2>
<h3>免费商用权益</h3>
<p>PicoServer 支持免费用于商业项目，无任何隐藏限制：</p>
<ul>
<li>无需支付授权费用</li>
<li>无需额外申请许可</li>
<li>可集成到商业产品中</li>
<li>可部署到终端设备上</li>
<li>可用于企业内部系统</li>
<li>可用于对外商业服务</li>
</ul>
<h3>版本维护承诺</h3>
<p>免费版将持续提供维护与更新服务，保障核心功能的稳定性与可用性，长期适配 .NET 生态更新。</p>
<h2>五、架构扩展性：低成本迁移 ASP.NET Core</h2>
<p>PicoServer 采用与主流 Web 框架兼容的设计思路，为未来项目扩展预留灵活空间：</p>
<ul>
<li>设计兼容：API 风格、核心概念（请求处理、路由、中间件）与 ASP.NET Core 保持一致</li>
<li>迁移优势：业务逻辑代码可直接复用，仅需调整少量入口配置与依赖引用</li>
<li>过渡价值：支持“先用 PicoServer 快速上线，后续低成本迁移到 ASP.NET Core”的渐进式开发模式，满足项目规模扩大后的生态扩展需求</li>
</ul>
<h2>六、技术服务与支持</h2>
<p>若您在使用过程中需要以下增值服务，可提供专业技术支持：</p>
<ul>
<li>性能优化：针对特定场景的性能调优</li>
<li>深度集成：与现有系统/设备的深度适配</li>
<li>定制功能：根据业务需求开发专属能力</li>
<li>项目合作：联合推进完整项目落地</li>
<li>技术支持：专属问题排查与解决方案提供</li>
<li>企业级解决方案：定制化的全流程技术方案</li>
</ul>
<h2>七、典型适用场景</h2>
<p>PicoServer 特别适配以下开发场景，可显著提升开发效率：</p>
<ol>
<li>WinForm/WPF 程序 Web 化改造</li>
<li>工控上位机远程控制功能开发</li>
<li>终端设备 Web 管理后台搭建</li>
<li>轻量数据采集与上报服务</li>
<li>WebSocket 实时通信系统（如设备监控、消息推送）</li>
<li>小型文件存储与传输服务</li>
<li>物联网网关数据转发服务</li>
<li>快速原型验证与演示项目开发</li>
</ol>
<h2>八、核心价值总结</h2>
<p>PicoServer 以“轻量、嵌入、零配置”为核心，提供“免费商用、稳定可靠”的 Web 能力解决方案，让开发者无需关注复杂的 Web 生态配置，快速为 .NET 程序赋能 Web 功能。</p>
<p>同时，通过低成本迁移设计与专业技术服务，为项目全生命周期提供支持，成为您开发过程中的“可靠技术伙伴”。</p>]]></description>
    <pubDate>Thu, 22 Jan 2026 10:15:54 +0800</pubDate>
    <dc:creator>PicoServer</dc:creator>
    <guid>https://docs.picoserver.cn/blog/20.html</guid>
</item>
<item>
    <title>🚀快速开始</title>
    <link>https://docs.picoserver.cn/quikstart.html</link>
    <description><![CDATA[<p><strong>像调用方法一样做 Web 开发</strong></p>
<blockquote>
<p>很多 .NET 开发者在桌面和设备领域经验丰富，但 Web 并不是主要方向。<br />
PicoServer 让你无需成为 Web 专家，也能为应用快速添加 Web 能力，就像你熟悉的方法调用一样自然。<br />
只需 1 分钟，即可搭建你的第一个 WebAPI 服务：</p>
</blockquote>
<h3>1. 安装 PicoServer 库</h3>
<ol>
<li>
<p>通过 NuGet 包管理器 <a href="https://www.nuget.org/packages/PicoServer/" title="PicoServer">安装 PicoServer</a>：<br />
<img src="https://docs.picoserver.cn/content/uploadfile/202601/b3bb1768225484.png" alt="30c11767350649.png" /></p>
</li>
<li>
<p>通过命令行安装</p>
<pre><code class="language-bash"># .NET CLI
dotnet add package PicoServer
# PMC
NuGet\Install-Package PicoServer</code></pre>
</li>
</ol>
<h3>2. C# 快速示例</h3>
<pre><code class="language-csharp">using System.Net;
using PicoServer;

namespace FastTestNamespace
{
    public static class FastTest
    {
        private static readonly WebAPIServer MyAPI = new WebAPIServer();

        public static void Main()
        {
            MyAPI.AddRoute("/", Hello); // 映射根路由
            MyAPI.StartServer(); // 启动服务（默认端口 8090）
            Console.WriteLine("PicoServer 启动成功！访问地址：http://127.0.0.1:8090");
            Console.ReadKey();
        }

        // 异步请求处理方法
        private static async Task Hello(HttpListenerRequest request, HttpListenerResponse response)
        {
            await response.WriteAsync("""{"code":1,"msg":"Hello WebAPI"}""");
        }
    }
}</code></pre>
<h3>3. VB.NET 快速示例</h3>
<pre><code class="language-vb">Imports System.Net
Imports PicoServer

Module FastTest
    Private ReadOnly MyAPI As New WebAPIServer
    Sub Main()
        MyAPI.AddRoute("/", AddressOf hello) '添加路由映射
        MyAPI.StartServer() '启动 WebAPI 服务,默认端口8090 传入参数可修改端口
        Console.WriteLine("访问地址：http://127.0.0.1:8090")
        Console.ReadKey()
    End Sub

    Private Async Function hello(request As HttpListenerRequest, response As HttpListenerResponse) As Task
        Await response.WriteAsync(&lt;t&gt;{"code":1,"msg":"Hello WebAPI"}&lt;/t&gt;.Value)
    End Function
End Module</code></pre>
<h3>4. 运行测试</h3>
<p>启动项目后，访问 <code>http://127.0.0.1:8090</code>，即可收到响应结果：</p>
<pre><code class="language-json">{"code":1,"msg":"Hello WebAPI"}</code></pre>]]></description>
    <pubDate>Thu, 01 Jan 2026 20:29:00 +0800</pubDate>
    <dc:creator>PicoServer</dc:creator>
    <guid>https://docs.picoserver.cn/quikstart.html</guid>
</item>
<item>
    <title>🍉使用示例（C#）</title>
    <link>https://docs.picoserver.cn/usage-csharp.html</link>
    <description><![CDATA[<blockquote>
<p>安装方式 参考 <a href="https://docs.picoserver.cn/quikstart.html">快速入门</a> </p>
<p>默认端口8090，传入参数则监听指定端口，Windows下注意赋予管理员权限</p>
<p>推荐使用 <strong>PicoServer</strong> 最新版本，保障功能完整性</p>
<p>由浅入深，完整的示例代码，直接复制粘贴即可运行并验证</p>
</blockquote>
<h2>1.最简 WebAPI</h2>
<pre><code class="language-csharp">private readonly WebAPIServer MyAPI = new WebAPIServer(); //实例化PicoServer

static void Main()
{
    MyAPI.AddRoute("/", Hello); //添加根路由映射
    MyAPI.StartServer();
    Console.WriteLine("http://127.0.0.1:8090");
    Console.ReadKey();
    MyAPI.StopServer(); //停止服务
}

//根路由映射的方法
private async Task Hello(HttpListenerRequest request, HttpListenerResponse response)
{
    await response.WriteAsync("Hello PicoServer");
}</code></pre>
<p><strong>相关方法</strong>：</p>
<pre><code class="language-csharp">MyAPI.AddRoute("/", Hello); //路由映射,不限制请求方法
MyAPI.AddRoute("/", Hello, "GET"); //路由映射，限定为 GET 方法

// 🚀 1.7+ 语义化路由 - 开发更爽，复杂应用so easy
MyAPI.MapGet("/", Hello);    // GET
MyAPI.MapPost("/", Hello);   // POST
MyAPI.MapPut("/", Hello);    // PUT
MyAPI.MapDelete("/", Hello); // DELETE

MyAPI.StartServer(); //开启服务
MyAPI.StartServer(8891); //开启服务,指定端口
MyAPI.StartServer("127.0.0.1"); //开启服务，限定为本机可访问（Pro版）
MyAPI.StartServer("127.0.0.1",8891); //开启服务，限定为本机可访问并指定端口（Pro版）
MyAPI.StopServer();  //停止服务
response.WriteAsync("Hello PicoServer"); //写入文本响应（UTF-8编码）
request.HttpMethod; //获取请求方法，可根据此实现同一个路由对不同请求方法进行不同处理</code></pre>
<h2>2.路由和参数解析</h2>
<blockquote>
<p>路由有四种风格。</p>
<ol>
<li>精准路由</li>
<li>星号路由</li>
<li>RESTful 风格路由(文档后面)</li>
<li>特性路由(Pro版)</li>
</ol>
</blockquote>
<pre><code class="language-csharp">private static readonly WebAPIServer MyAPI = new WebAPIServer();

static void Main()
{
    // 注册精确路由（优先级高于通配符路由）
    MyAPI.AddRoute("/api/user/query", QueryUser, "GET");
    MyAPI.AddRoute("/api/user/save", SaveUser, "POST");
    MyAPI.AddRoute("/api/user/json", SaveUserJson, "POST");

    // 注册星号通配符路由（每段 URL 仅支持一个 *，支持多段通配）
    MyAPI.AddRoute("/api/*/posts", HandleWildcardPost, "POST");
    MyAPI.AddRoute("/api/*/user/*/detail", HandleMultiWildcard, "GET");

    // 启动服务
    MyAPI.StartServer();
    Console.WriteLine("服务已启动 http://127.0.0.1:8090");
    Console.ReadKey();
    MyAPI.StopServer();
}

//处理 GET 查询参数请求
//路由：/api/user/query
private static async Task QueryUser(HttpListenerRequest request, HttpListenerResponse response)
{
    string name = request.GetQuery("name");
    int age = request.GetQuery&lt;int&gt;("age");
    bool isVip = request.GetQuery&lt;bool&gt;("isVip");

    string output = $@"{{
        ""code"": 1,
        ""msg"": ""参数解析成功"",
        ""data"": {{ 
            ""name"": ""{name}"", 
            ""age"": {age}, 
            ""isVip"": {isVip} 
        }}
    }}";
    await response.WriteAsync(output);
}

//处理 POST 表单数据请求
//路由：/api/user/save
//Content-Type: application/x-www-form-urlencoded
private static async Task SaveUser(HttpListenerRequest request, HttpListenerResponse response)
{
    var formData = request.ParseForm();
    string userName = formData["userName"];
    string phone = formData["phone"];
    await response.WriteAsync($"{{""code"":1, ""msg"":""表单保存成功"",""data"":{{""userName"":""{userName}"",""phone"":""{phone}""}}}}");
}

//处理 POST JSON 数据请求
//路由： /api/user/json
//Content-Type: application/json
private static async Task SaveUserJson(HttpListenerRequest request, HttpListenerResponse response)
{
    string bodyJson = await request.ReadBodyAsStringAsync();
    await response.WriteAsync($"{{""code"":1, ""msg"":""JSON 保存成功"",""data"":{bodyJson}}}");
}

//处理单层星号通配符 POST 请求
//路由：POST /api/*/posts（匹配 /api/xxx/posts，* 为任意单段路径）
//内置防目录遍历，自动拦截 ../ 等非法字符
private static async Task HandleWildcardPost(HttpListenerRequest request, HttpListenerResponse response)
{
    string requestUrl = request.Url.AbsolutePath;
    string bodyJson = await request.ReadBodyAsStringAsync();
    string output = $@"{{
        ""code"": 1,
        ""msg"": ""通配符路由匹配成功"",
        ""data"": {{
            ""requestUrl"": ""{requestUrl}"",
            ""receivedData"": {bodyJson}
        }}
    }}";
    await response.WriteAsync(output);
}

//处理多层星号通配符 GET 请求
// 路由：GET /api/*/user/*/detail（匹配 /api/xxx/user/yyy/detail，每段一个 *）
private static async Task HandleMultiWildcard(HttpListenerRequest request, HttpListenerResponse response)
{
    string requestUrl = request.Url.AbsolutePath;
    string output = $"{{""code"":1,""msg"":""多层通配符匹配成功"",""requestUrl"":""{requestUrl}""}}";
    await response.WriteAsync(output);
}</code></pre>
<p><strong>相关方法</strong></p>
<pre><code class="language-csharp">request.GetQuery();//获取指定查询参数，不存在则返回null
request.GetQuery&lt;T&gt;(); //按类型返回指定查询参数，失败返回类型默认值
request.ParseForm(); //获取表单数据
request.ReadBodyAsStringAsync(); //获取 body 字符串
request.Items(); //获取当前请求的扩展属性字典。用于在不同中间件之间传递和共享数据。【Pro版】</code></pre>
<h2>3.Cookie 增删改查</h2>
<pre><code class="language-csharp">static void Main()
{
    MyAPI.AddRoute("/cookie/set", SetCookie, "GET");
    MyAPI.AddRoute("/cookie/get", GetCookie, "GET");
    MyAPI.AddRoute("/cookie/delete", DeleteCookie, "GET");
    MyAPI.AddRoute("/cookie/clear", ClearCookies, "GET");

    MyAPI.StartServer(8090);
    Console.WriteLine("Cookie 测试服务已启动：http://127.0.0.1:8090");
    Console.ReadKey();
    MyAPI.StopServer();
}

// 设置 Cookie（支持过期时间、路径、HttpOnly）
private async Task SetCookie(HttpListenerRequest request, HttpListenerResponse response)
{
    // 添加普通 Cookie（1小时过期）
    response.AppendCookie("token", "pico_1234567", new CookieOptions 
    {
            Expires = DateTimeOffset.Now.AddHours(1),
            Path = "/",
            HttpOnly = true // 防止前端 JS 读取，提升安全性
    });
    // 添加自定义路径 Cookie
    response.AppendCookie("theme", "dark", new CookieOptions 
    {
            Expires = DateTimeOffset.Now.AddDays(7),
            Path = "/"
    });
    response.BuildCookie(); //关键，多个Cookie需进行拼接
    await response.WriteAsync(@"{""code"":1, ""msg"":""Cookie 设置成功""}");
}

// 读取 Cookie
private async Task GetCookie(HttpListenerRequest request, HttpListenerResponse response)
{
    // 安全读取 Cookie（避免空引用）
    string token = null;
    request.TryGetCookieValue("token", out token);
    string theme = null;
    request.TryGetCookieValue("theme", out theme);

    await response.WriteAsync($@"{{""code"":1, ""token"":""{token}"",""theme"":""{theme}""}}");
}

// 删除指定 Cookie
private async Task DeleteCookie(HttpListenerRequest request, HttpListenerResponse response)
{
    response.DeleteCookie("token", new CookieOptions { Path = "/" });
    await response.WriteAsync(@"{""code"":1, ""msg"":""Token Cookie 删除成功""}");
}

// 批量清理所有 Cookie
private async Task ClearCookies(HttpListenerRequest request, HttpListenerResponse response)
{
    response.ClearCookies();
    await response.WriteAsync(@"{""code"":1, ""msg"":""所有 Cookie 已清理""}");
}</code></pre>
<h2>4.RESTful 风格路由</h2>
<pre><code class="language-csharp">private readonly WebAPIServer MyAPI = new WebAPIServer();

static void Main()
{
    MyAPI.AddRoute("/users", Users);
    MyAPI.StartServer();
    Console.WriteLine("服务已启动：http://127.0.0.1:8090");
    Console.ReadKey();
    MyAPI.StopServer();
}

private async Task Users(HttpListenerRequest request, HttpListenerResponse response)
{
    response.ContentType = GetContentType(".json");
    switch (request.HttpMethod)
    {
        case "GET":
            await response.WriteAsync(@"{""code"":1,""msg"":""获取用户成功"",""data"":{""username"":""PicoServer""}}");
            break;
        case "POST":
            response.StatusCode = 201;
            await response.WriteAsync(@"{""code"":1,""msg"":""创建用户成功"",""data"":{""userId"":""123456""}}");
            break;
        default:
            response.StatusCode = 405;
            await response.WriteAsync(@"{""code"":0,""msg"":""方法不允许""}");
            break;
    }
}</code></pre>
<p><strong>相关方法</strong></p>
<pre><code class="language-csharp">GetContentType(".html"); //根据文件扩展名获取 MIME 类型：text/html;charset=UTF-8</code></pre>
<p><code>GetContentType</code> 为跨平台通用方法（Windows/Linux/Docker 结果一致），可根据文件扩展名获取标准化 MIME 类型，支持的扩展名有：.html/.htm、.css、.js、.json、.txt、.xml、.jpg/.jpeg、.png、.gif、.webp、.svg/.svgz、.ico、.mp4、.webm、.mp3、.wav、.m3u8、.ts、.woff2、.woff、.ttf、.otf、.pdf、.zip、.rar、.7z、.apk；文本类类型默认带 UTF-8 编码，未知类型返回 application/octet-stream。</p>
<h2>5.特性路由</h2>
<blockquote>
<p>标记特性即可自动注册路由，构建高级应用更爽快。免费版完全支持 AOT ，但特性路由通过扩展包<code>PicoServer.Extensions</code>反射实现，Pro 版特性路由支持 AOT</p>
</blockquote>
<pre><code class="language-csharp">[ApiController]
public class UserController
{
    [ApiRoute("/api/user", "GET")]
    public async Task GetUser(HttpListenerRequest req, HttpListenerResponse res)
    {
        await res.WriteAsync("{\"id\":1,\"name\":\"张三\"}", WebAPIServer.ContentType.ApplicationJson);
    }

    [ApiRoute("/api/user", "POST")]
    public async Task CreateUser(HttpListenerRequest req, HttpListenerResponse res)
    {
        await res.WriteAsync("{\"success\":true}", WebAPIServer.ContentType.ApplicationJson);
    }
}</code></pre>
<p><strong>相关函数</strong></p>
<pre><code class="language-csharp">MyAPI.AutoRegisterRoutes();//自动注册特性路由</code></pre>
<h2>6.静态文件托管</h2>
<blockquote>
<p>静态文件（HTML/CSS/JS/ 图片 / 视频）托管配置，适配前端页面直接访问、静态资源服务等场景。如B/S架构的网站应用</p>
</blockquote>
<pre><code class="language-csharp">internal readonly WebAPIServer MyAPI = new WebAPIServer();

static void Main()
{
    //添加静态文件服务， wwwroot 目录
    MyAPI.AddStaticFiles("/", "wwwroot");
    MyAPI.AddCors(); //允许跨域
    MyAPI.StartServer();
    //保持程序作为服务运行,兼容windows和linux
    Console.WriteLine("服务器已启动，按Ctrl+C退出...");
    Thread.Sleep(Timeout.Infinite);
}</code></pre>
<p><strong>相关函数</strong></p>
<pre><code class="language-csharp">//添加静态文件服务。第一个参数为路由，第二个为服务端文件夹（相对/绝对路径），没有匹配到文件则回到路由匹配
MyAPI.AddStaticFiles("/", "wwwroot");//默认开启自动识别缓存
app.AddStaticFiles("/web", "www", 2592000);  // 缓存30 天
MyAPI.AddCors(); //启用跨域</code></pre>
<h2>7.跨域配置</h2>
<blockquote>
<p>解决前后端分离跨域限制，支持极简配置与自定义配置</p>
</blockquote>
<pre><code class="language-csharp">MyAPI.AddCors(); //启用跨域，默认允许所有来源/方法/请求头
MyAPI.AddCors("picoserver.cn"); //支持指定跨域
//更多个性化跨域自定义跨域中间件即可。</code></pre>
<h2>8.文件上传/下载</h2>
<pre><code class="language-csharp">private readonly WebAPIServer MyAPI = new WebAPIServer();

static void Main()
{
    MyAPI.AddRoute("/file/download", DownloadFile, "GET");    // 文件下载/预览
    MyAPI.AddRoute("/file/upload", UploadFile, "POST");       // 文件上传

    MyAPI.StartServer();
    Console.WriteLine("文件服务已启动：http://127.0.0.1:8090");
    Console.ReadKey();
    MyAPI.StopServer();
}

// 文件下载/预览（asAttachment=false 预览，true 强制下载）
private async Task DownloadFile(HttpListenerRequest request, HttpListenerResponse response)
{
    string TestFile = "D:\\test.mp4";
    if (!File.Exists(TestFile))
    {
        await response.WriteAsync(@"{""code"":0, ""msg"":""文件不存在""}");
        return;
    }
    await response.SendFileAsync(TestFile, true);
}

// 文件上传（带进度回调）
private async Task UploadFile(HttpListenerRequest request, HttpListenerResponse response)
{
    string fname = request.Headers["filename"]; //从请求头中获取文件名（test112.mp4），示例为相对位置，中文文件名建议用BASE64编码或者URL编码
    bool isSuccess = await request.SaveFileAsync(fname, (current, total) =&gt; 
    {
        // 打印上传进度（百分比）
        Console.WriteLine($"上传进度：{ current * 100 / total}%");
    });

    if (isSuccess)
    {
        await response.WriteAsync(@"{""code"":1, ""msg"":""文件上传成功""}");
    }
    else
    {
        await response.WriteAsync(@"{""code"":0, ""msg"":""文件上传失败""}");
    }
    Console.WriteLine($"请求头中的文件名：{fname}");
}</code></pre>
<p><strong>相关函数</strong></p>
<pre><code class="language-csharp">//发送文件，支持断点下载
response.SendFileAsync();//流式发送，大文件低内存消耗，根据扩展名自动添加文件类型
response.SendFileAsync(filePath);//支持文档/视频等直接预览
response.SendFileAsync(filePath,true);//强制下载
response.SendFileAsync(Mp4Path,false,request);//播放视频，支持拖动播放
//接受文件上传，支持断点续传
request.SaveFileAsync();//流式保存，大文件低内存消耗
request.SaveFileAsync(filePath);//保存文件到指定路径（相对/绝对皆可），需要包含文件名
request.SaveFileAsync(filePath,onProgress);//保存文件到指定路径，支持回调进度。

request.Headers["filename"]; //举例：从请求头中获取文件名，生产中应进行非空判断</code></pre>
<h2>9.流媒体/直播流推送</h2>
<pre><code class="language-csharp">private readonly WebAPIServer MyAPI = new WebAPIServer();

static void Main()
{
    MyAPI.AddRoute("/stream/live", LiveStream, "GET"); // 直播流推送
    MyAPI.StartServer();
    Console.WriteLine("流媒体服务已启动：http://127.0.0.1:8090");
    Console.ReadKey();
    MyAPI.StopServer();
}

private async Task LiveStream(HttpListenerRequest request, HttpListenerResponse response)
{
    string LiveFile = "D:\\test.mp4"; // 直播源文件（可替换为实时流）
    if (!File.Exists(LiveFile))
    {
        await response.WriteAsync(@"{""code"":0, ""msg"":""直播源不存在""}");
        return;
    }

    // 打开文件流（FileShare.ReadWrite 允许文件被其他程序写入）
    using (FileStream fs = new FileStream(LiveFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
    {
        await response.SendStreamAsync(fs, GetContentType(".mp4"), true);
    }
}</code></pre>
<p><strong>相关方法</strong></p>
<pre><code class="language-csharp">response.SendStreamAsync(fs, GetContentType(".mp4"), true);//无缓存、Chunked 传输，适配实时流，各种流</code></pre>
<h2>10.简单 Token/JWT 鉴权</h2>
<blockquote>
<p>一旦添加鉴权，默认所有路由都需要鉴权，不需要鉴权的路由需要添加到路由白名单</p>
<p>白名单只针对精准路由（路径），不支持星号路由</p>
</blockquote>
<h4>路由白名单</h4>
<pre><code class="language-csharp">MyAPI.RouteWhiteList; //储存路由白名单的集合
MyAPI.RouteWhiteList.Add("/api/login"); //添加接口到白名单，无需验证</code></pre>
<h4><strong>简单token鉴权</strong></h4>
<pre><code class="language-csharp">private readonly WebAPIServer MyAPI = new WebAPIServer();
private string _testToken = "PicoServer123"; // 测试用 Token

static void Main()
{
    MyAPI.AddRoute("/api/login", Login, "POST");
    MyAPI.AddRoute("/api/user/info", GetUserInfo, "GET");

    //配置白名单（放行登录接口）
    MyAPI.RouteWhiteList.Add("/api/login");
    MyAPI.AddSimpleTokenVerify(_testToken);

    MyAPI.StartServer();
    Console.WriteLine($"鉴权服务已启动，测试 Token：{_testToken}");
    Console.ReadKey();
    MyAPI.StopServer();
}

// 登录接口（白名单，无需鉴权）
private async Task Login(HttpListenerRequest request, HttpListenerResponse response)
{
    await response.WriteAsync($@"{{""code"":1, ""msg"":""登录成功"",""token"":""{_testToken}""}}");
}

// 用户信息接口（需鉴权，非白名单）
private async Task GetUserInfo(HttpListenerRequest request, HttpListenerResponse response)
{
    string token = request.GetToken();
    await response.WriteAsync($@"{{""code"":1, ""msg"":""获取信息成功"",""token"":{token}}}");
}</code></pre>
<p><strong>相关方法</strong></p>
<pre><code class="language-csharp">MyAPI.AddSimpleTokenVerify(testToken); //添加简单 token 验证中间件，参数为token
request.GetToken(); //获取请求头中的token值</code></pre>
<h4><strong>JWT鉴权</strong></h4>
<pre><code class="language-csharp">private readonly WebAPIServer MyAPI = new WebAPIServer();
private string _testToken; // 测试用 Token

static void Main()
{
    // 1. 注册路由（先注册，后配置鉴权）
    MyAPI.AddRoute("/api/login", Login, "POST");       // 白名单路由（无需鉴权）
    MyAPI.AddRoute("/api/user/info", GetUserInfo, "GET"); // 需鉴权路由

    // 2. 配置白名单（放行登录接口）
    MyAPI.RouteWhiteList.Add("/api/login");

    // 3. 启用 JWT 鉴权（密钥需与生成 Token 时一致）
    MyAPI.AddJwtTokenVerify("pico_secret_779");

    // 4. 生成测试 Token（模拟登录成功）
    GenerateTestToken();

    MyAPI.StartServer();
    Console.WriteLine($"鉴权服务已启动，测试 Token：{_testToken}");
    Console.ReadKey();
    MyAPI.StopServer();
}

// 简化版：生成测试 JWT Token
private void GenerateTestToken()
{
    // 过期时间：当前+1小时（10位时间戳）
    long exp = MyAPI.GetTimeStamp10(3600);
    // 直接使用字符串插值构造载荷，简化代码
    string payload = $@"{{""username"":""admin"",""role"":""super"",""exp"":{exp}}}";
    // 生成 Token
    _testToken = MyAPI.Jwt.GenerateToken(payload);
}

// 登录接口（白名单，无需鉴权）
private async Task Login(HttpListenerRequest request, HttpListenerResponse response)
{
    // 模拟登录验证（实际场景替换为账号密码校验）
    await response.WriteAsync($@"{{""code"":1, ""msg"":""登录成功"",""token"":""{_testToken}""}}");
}

// 用户信息接口（需鉴权，非白名单）
private async Task GetUserInfo(HttpListenerRequest request, HttpListenerResponse response)
{
    // 获取请求头中的 Token 并解析载荷
    string token = request.GetToken();
    string payload = MyAPI.Jwt.DecodePayload(token);

    await response.WriteAsync($@"{{""code"":1, ""msg"":""获取信息成功"",""userInfo"":{payload}}}");
}</code></pre>
<p><strong>相关方法</strong></p>
<blockquote>
<p>PicoServer.Crypto（Pro版）</p>
</blockquote>
<pre><code class="language-csharp">MyAPI.AddJwtTokenVerify("pico_secret_779");//添加 JWT 鉴权中间件，参数为HS256加密密钥
MyAPI.AddJwtTokenVerify("pico_secret_779",PicoServer.Crypto.HashType.SM3); //添加 JWT 鉴权中间件，参数为 HMAC-SM3 加密密钥

request.GetToken(); //获取请求头中的token值
MyAPI.Jwt.DecodePayload(token);//解码 JWT 负载为字符串
MyAPI.Jwt.GenerateToken(payload); //创建 JWT token 参数为负载，用于储存信息

MyAPI.GetTimeStamp10(3600); // 获取10位时间戳，参数：需要追加的秒数，不传入则返回当前时间戳
MyAPI.GetTimeStamp13(); // 获取13位时间戳，参数：需要追加的毫秒数，不传入则返回当前时间戳

// 加密工具（PicoServer.Crypto）
string signature = HS256.ComputeHmac256(data, key); // HMAC-SHA256 签名
byte[] hash = SM3.ComputeHash(data); // SM3 哈希计算
string hmacSm3 = SM3.ComputeHmacSM3(data, key); // HMAC-SM3 签名
string passwordHash = SM3.HashPassword(password, salt, iterations); // SM3 密码哈希
string encoded = Base64Url.Encode(data); // Base64Url 编码
string decoded = Base64Url.Decode(encoded); // Base64Url 解码</code></pre>
<h2>11.SSE服务端推送</h2>
<pre><code class="language-csharp">private readonly WebAPIServer MyAPI = new WebAPIServer();

static void Main()
{
    MyAPI.AddRoute("/iot/notify", Notify, "GET"); // SSE推送
    MyAPI.StartServer(8090);
    Console.WriteLine("SSE推送服务已启动：http://127.0.0.1:8090/iot/notify");
    Console.ReadKey();
    MyAPI.StopServer();
}

// SSE推送消息推送（模拟设备报警）
public static async Task Notify(HttpListenerRequest request, HttpListenerResponse response)
{
    response.ContentType = "text/event-stream";
    response.Headers.Add("Cache-Control", "no-cache");
    response.SendChunked = true;

    try
    {
        for (int i = 0; i &lt; 5; i++)
        {
            string msg = $"data: 消息推送 {i} 时间: {DateTime.Now}\n\n";
            byte[] buffer = System.Text.Encoding.UTF8.GetBytes(msg);
            await response.OutputStream.WriteAsync(buffer, 0, buffer.Length);
            await response.OutputStream.FlushAsync();
            await Task.Delay(1000);
        }
    }
    finally
    {
        //在使用 HttpListenerResponse 进行 SSE（Server - Sent Events）推送时，response.Close(); 并不是必须的，但推荐在推送结束后调用它，以确保资源释放和连接正确关闭。
        // 示例这里是推送结束后调用 response.Close();，确保响应流关闭
        // 如果是无限推送（如实时设备报警），不要关闭响应，直到客户端断开。
        response.Close();
    }
}</code></pre>
<p>前端 JavaScript 示例(如果测试时候不能访问，注意开启跨域)</p>
<pre><code class="language-js">function startSSE() {
    const source = new EventSource("/iot/notify");
    source.onmessage = function (event) {
        document.getElementById("result").innerHTML += event.data + "&lt;br&gt;";
    };
    source.onerror = function () {
        source.close();
    };
}</code></pre>
<p><strong>PicoServer SSE 在线测试工具</strong> <a href="https://picoserver.cn/tools/ssetest.html">https://picoserver.cn/tools/ssetest.html</a></p>
<h2>12.长连接消息推送</h2>
<pre><code class="language-csharp">private readonly WebAPIServer MyAPI = new WebAPIServer();

static void Main()
{
    MyAPI.AddRoute("/notify", LongConnectionPush, "GET"); // 长连接推送
    MyAPI.StartServer(8090);
    Console.WriteLine("长连接服务已启动：http://127.0.0.1:8090/notify");
    Console.ReadKey();
    MyAPI.StopServer();
}

// 长连接消息推送（模拟设备报警）
private async Task LongConnectionPush(HttpListenerRequest request, HttpListenerResponse response)
{
    try
    {
        // 循环推送消息（实际场景替换为业务事件触发）
        for (int i = 0; i &lt;= 29; i++)
        {
            // 推送报警消息（低内存）
            await response.WriteChunkAsync($"设备报警 {i}：温度异常 {DateTime.Now:HH:mm:ss}" + "\r\n");
            // 模拟 1 秒推送一次
            await Task.Delay(1000);
        }

        // 推送结束，发送结束标识
        await response.WriteChunkAsync("推送结束");
    }
    finally
    {
        // 示例这里是推送结束后调用 response.Close();，确保响应流关闭
        // 如果是无限推送（如实时设备报警），不要关闭响应，直到客户端断开。
        response.Close();
    }
}</code></pre>
<p><strong>相关方法</strong></p>
<pre><code class="language-csharp">response.WriteChunkAsync("推送结束"); //推送字符串
response.Close(); //关闭响应，释放资源 【WriteChunkAsync下必须手动关闭，避免资源泄露】</code></pre>
<h2>13.WebSocket 通信</h2>
<ul>
<li>
<p>场景目标：实现 WebSocket 双向交互，适配实时聊天、设备指令交互等场景</p>
</li>
<li>
<p>核心要点：服务端（enableWebSocket 启用、事件订阅、在线客户端管理、广播消息）、客户端（WebSocketClient 初始化、事件订阅、消息发送）</p>
</li>
<li>
<p>运行测试：服务端启动、客户端连接、双向消息交互、广播消息接收</p>
</li>
</ul>
<blockquote>
<p>WebSocket 服务端可以和 WebAPI 同时存在，且共用端口，共用地址<br />
<strong>WebSocket 在线测试工具 <a href="https://wstool.js.org/">https://wstool.js.org/</a></strong></p>
</blockquote>
<h4>WebSocket 服务端</h4>
<pre><code class="language-csharp">private readonly WebAPIServer MyAPI = new WebAPIServer();

static void Main()
{
    MyAPI.enableWebSocket = true;
    MyAPI.WsOnConnectionChanged = WsConnectChanged;
    MyAPI.WsOnMessage = OnMessageReceived;

    MyAPI.StartServer();
    Console.WriteLine("PicoServer WebSocket：http://127.0.0.1:8090");
    Console.ReadKey();
    MyAPI.StopServer();
}

private async Task WsConnectChanged(string clientId, bool connected)
{
    await MyAPI.WsBroadcastAsync($"{clientId} {connected}");
}

private async Task OnMessageReceived(string clientId, string message, Func&lt;string, Task&gt; reply)
{
    await reply("收到！");
    var clients = MyAPI.WsGetOnlineClients();
    foreach (var client in clients)
    {
        await MyAPI.WsSendToClientAsync(client, $"{clientId}说：{message}");
    }
}</code></pre>
<p><strong>相关方法</strong></p>
<pre><code class="language-csharp">MyAPI.enableWebSocket = true; //启用WebSocket支持
MyAPI.WsOnConnectionChanged; // 事件：WebSocket客户端连接状态发生变化
MyAPI.WsOnMessage; //事件：收到WebSocket客户端发送来的消息
MyAPI.WsBroadcastAsync(); //对所有在线客户端广播消息
MyAPI.WsGetOnlineClients; //获取在线客户端列表
MyAPI.WsSendToClientAsync(client,message); //给指定客户端发送消息
MyAPI.WsEnableHeartbeat = true; //启用 WebSocket 服务端心跳检测，默认false
MyAPI.WsHeartbeatTimeout = 60; //设置 WebSocket 心跳时间，默认30秒
MyAPI.WsMaxConnections = 200; //设置 WebSocket 最大连接数，默认100
MyAPI.WsPingString = "hi"; //设置 WebSocket 的ping消息，默认"ping"，不区分大小写</code></pre>
<h4>WebSocket 客户端</h4>
<pre><code class="language-csharp">private WebSocketClient wsClient = new WebSocketClient("wss://echo.websocket.org/");

static void Main()
{
    // 订阅核心事件
    wsClient.OnConnected += OnConnected; // 连接成功
    wsClient.OnMessageReceived += OnMessageReceived; // 接收消息
    wsClient.OnDisconnected += OnDisconnected; // 连接断开
    wsClient.OnError += OnError; // 异常触发
    wsClient.StartConnect();
    Console.ReadKey();
    wsClient.StopConnect();
}

private void OnConnected(object sender, EventArgs e)
{
    Console.WriteLine("连接成功！");
}

private void OnMessageReceived(object sender, string message)
{
    Console.WriteLine($"收到消息: {message}");
    wsClient.SendMessageAsync($"hi: {DateTime.Now.ToShortTimeString()}");
}

private void OnDisconnected(object sender, EventArgs e)
{
    Console.WriteLine("连接已断开！");
}

private void OnError(object sender, WebSocketErrorEventArgs e)
{
    Console.WriteLine($"错误: {e.ErrorCode}, {e.ErrorMessage}");
}</code></pre>
<p><strong>相关方法</strong></p>
<pre><code class="language-csharp">private WebSocketClient wsClient = new WebSocketClient(); //实例化WebSocket客户端
private WebSocketClient wsClient = new WebSocketClient("wss://echo.websocket.org/"); //实例化WebSocket服务端，支持ws和wss,默认5秒超时
private WebSocketClient wsClient = new WebSocketClient("wss://echo.websocket.org/",10); //自定义超时时间10秒

wsClient.StartConnect(); //连接服务端
wsClient.StopConnect();  //断开连接
wsClient.SendMessageAsync(message); //发送消息
wsClient.SendPingAsync(); //发送ping消息，默认“ping”
wsClient.SendPingAsync("hi"); //发送自定义ping消息</code></pre>
<h2>14.高级用法和中间件</h2>
<blockquote>
<p>PicoServer 开放了 <strong>中间件</strong> ，可以借此进行二次开发、封装、集成解决方案等 。</p>
<p>利用 AddMiddleware() 可开发属于自己的中间件。比如：参数路由，限流，黑名单等等。</p>
</blockquote>
<h3>极简文件服务器</h3>
<pre><code class="language-csharp">using PicoServer;

var MyAPI = new WebAPIServer();
string rootPath = @"D:\MyFiles"; // 设定你的物理资源根目录

// 1. 首页：列出所有文件 (简单 WebAPI)
MyAPI.AddRoute("/files", async (req, resp) =&gt; {
    var files = Directory.GetFiles(rootPath).Select(Path.GetFileName);
    var html = $$"""
        &lt;h1&gt;文件清单&lt;/h1&gt;
        &lt;ul&gt;
            {{string.Join("", files.Select(f =&gt; $"&lt;li&gt;&lt;a href='/view?name={f}'&gt;{f}&lt;/a&gt;&lt;/li&gt;"))}}
        &lt;/ul&gt;
        """;
    await resp.WriteAsync(html, WebAPIServer.ContentType.TextHtml);
}, "GET");

// 2. 查看/预览：支持视频拖动播放 (利用 asAttachment: false)
MyAPI.AddRoute("/view", (req, resp) =&gt; {
    string fileName = req.ParseGetQueryString("name");
    string fullPath = Path.Combine(rootPath, fileName);

    // asAttachment: false 允许浏览器直接播放视频或预览图片
    return resp.SendFileAsync(fullPath, asAttachment: false);
}, "GET");

// 3. 强制下载：(默认 asAttachment: true)
MyAPI.AddRoute("/download", (req, resp) =&gt; {
    string fileName = req.ParseGetQueryString("name");
    return resp.SendFileAsync(Path.Combine(rootPath, fileName));
}, "GET");

MyAPI.StartServer(8090);
Console.WriteLine("文件服务器已启动: http://127.0.0.1:8090");
</code></pre>
<hr />
<h3>自定义中间件</h3>
<blockquote>
<p>这个示例演示了如何利用自定义中间件的扩展功能实现<strong>动态路由</strong>，在一个逻辑块内完成<strong>路径匹配</strong>、<strong>方法分发</strong>和<strong>请求终结</strong>，从而灵活的自定义各种中间件。<strong>注意：中间件的执行是按添加顺序执行的</strong></p>
</blockquote>
<p><strong> 极简动态路由 </strong></p>
<pre><code class="language-csharp">using PicoServer;
using System.Text.RegularExpressions;

var MyAPI = new WebAPIServer();

// 【提示】前置鉴权/日志中间件应在此处注册

// 极简动态路由：建议作为最后的处理器
MyAPI.AddMiddleware(async (req, resp) =&gt; {
    // 匹配 /product/123 这种带 ID 的路径
    var match = Regex.Match(req.Url.AbsolutePath, @"^/product/(?&lt;id&gt;\d+)$");

    if (match.Success) {
        string id = match.Groups["id"].Value;

        // 根据请求方式 (Method) 分发逻辑
        switch (req.HttpMethod) {
            case "GET":
                await resp.WriteAsync($$"""{"action":"查询商品", "id":{{id}}}""");
                break;
            case "POST":
                await resp.WriteAsync($$"""{"action":"更新商品", "id":{{id}}, "result":"Success"}""");
                break;
            default:
                resp.StatusCode = 405;
                await resp.WriteAsync("""{"msg":"不支持的操作"}""");
                break;
        }

        return false; // 【核心】匹配成功并处理，返回 false 终结请求，不再走默认路由
    }

    return true; // 没匹配上，放行给后续逻辑或 404，如果是自定义路由建议放在最后，且只返回false，不再继续分发。
});

MyAPI.StartServer(8090);
</code></pre>]]></description>
    <pubDate>Wed, 31 Dec 2025 22:00:35 +0800</pubDate>
    <dc:creator>PicoServer</dc:creator>
    <guid>https://docs.picoserver.cn/usage-csharp.html</guid>
</item>
<item>
    <title>🍉使用示例（VB.NET）</title>
    <link>https://docs.picoserver.cn/usage-vbnet.html</link>
    <description><![CDATA[<blockquote>
<p>安装方式 参考 <a href="https://docs.picoserver.cn/quikstart.html">快速入门</a> </p>
<p>默认端口8090，传入参数则监听指定端口，Windows下注意赋予管理员权限</p>
<p>推荐使用 <strong>PicoServer</strong> 最新版本，保障功能完整性</p>
<p>由浅入深，完整的示例代码，直接复制粘贴即可运行并验证</p>
</blockquote>
<h2>1.最简 WebAPI</h2>
<pre><code class="language-vb">Private ReadOnly MyAPI As New WebAPIServer() '实例化PicoServer

Sub Main()
    MyAPI.AddRoute("/", AddressOf Hello) '添加根路由映射
    MyAPI.StartServer()
    Console.WriteLine("http://127.0.0.1:8090")
    Console.ReadKey()
    MyAPI.StopServer() '停止服务
End Sub

'根路由映射的方法
Private Async Function Hello(request As HttpListenerRequest, response As HttpListenerResponse) As Task
    Await response.WriteAsync("Hello PicoServer")
End Function</code></pre>
<p><strong>相关方法</strong>：</p>
<pre><code class="language-vb">MyAPI.AddRoute("/", AddressOf Hello) '路由映射,不限制请求方法
MyAPI.AddRoute("/", AddressOf Hello, "GET") '路由映射，限定为 GET 方法

' 🚀 1.7+ 语义化路由 - 开发更爽，复杂应用so easy
MyAPI.MapGet("/", AddressOf Hello)    ' GET
MyAPI.MapPost("/", AddressOf Hello)   ' POST
MyAPI.MapPut("/", AddressOf Hello)    ' PUT
MyAPI.MapDelete("/", AddressOf Hello) ' DELETE

MyAPI.StartServer() '开启服务
MyAPI.StartServer(8891) '开启服务,指定端口
MyAPI.StartServer("127.0.0.1") '开启服务，限定为本机可访问（Pro版）
MyAPI.StartServer("127.0.0.1",8891) '开启服务，限定为本机可访问并指定端口（Pro版）
MyAPI.StopServer()  '停止服务
response.WriteAsync("Hello PicoServer") '写入文本响应（UTF-8编码）
request.HttpMethod '获取请求方法，可根据此实现同一个路由对不同请求方法进行不同处理</code></pre>
<h2>2.路由和参数解析</h2>
<blockquote>
<p>路由有四种风格。</p>
<ol>
<li>精准路由</li>
<li>星号路由</li>
<li>RESTful 风格路由(文档后面)</li>
<li>特性路由(Pro版)</li>
</ol>
</blockquote>
<pre><code class="language-vb">Private Shared ReadOnly MyAPI As New WebAPIServer()

Sub Main()
    ' 注册精确路由（优先级高于通配符路由）
    MyAPI.AddRoute("/api/user/query", AddressOf QueryUser, "GET")
    MyAPI.AddRoute("/api/user/save", AddressOf SaveUser, "POST")
    MyAPI.AddRoute("/api/user/json", AddressOf SaveUserJson, "POST")

    ' 注册星号通配符路由（每段 URL 仅支持一个 *，支持多段通配）
    MyAPI.AddRoute("/api/*/posts", AddressOf HandleWildcardPost, "POST")
    MyAPI.AddRoute("/api/*/user/*/detail", AddressOf HandleMultiWildcard, "GET")

    ' 启动服务
    MyAPI.StartServer()
    Console.WriteLine("服务已启动 http://127.0.0.1:8090")
    Console.ReadKey()
    MyAPI.StopServer()
End Sub

'处理 GET 查询参数请求
'路由：/api/user/query
Private Shared Async Function QueryUser(request As HttpListenerRequest, response As HttpListenerResponse) As Task
    Dim name As String = request.GetQuery("name")
    Dim age As Integer = request.GetQuery(Of Integer)("age")
    Dim isVip As Boolean = request.GetQuery(Of Boolean)("isVip")

    Dim output As String = $"{{
        ""code"": 1,
        ""msg"": ""参数解析成功"",
        ""data"": {{ 
            ""name"": ""{name}"", 
            ""age"": {age}, 
            ""isVip"": {isVip.ToString().ToLower()} 
        }}
    }}"
    Await response.WriteAsync(output)
End Function

'处理 POST 表单数据请求
'路由：/api/user/save
'Content-Type: application/x-www-form-urlencoded
Private Shared Async Function SaveUser(request As HttpListenerRequest, response As HttpListenerResponse) As Task
    Dim formData = request.ParseForm()
    Dim userName As String = formData("userName")
    Dim phone As String = formData("phone")
    Await response.WriteAsync($"{{""code"":1, ""msg"":""表单保存成功"",""data"":{{""userName"":""{userName}"",""phone"":""{phone}""}}}}")
End Function

'处理 POST JSON 数据请求
'路由： /api/user/json
'Content-Type: application/json
Private Shared Async Function SaveUserJson(request As HttpListenerRequest, response As HttpListenerResponse) As Task
    Dim bodyJson As String = Await request.ReadBodyAsStringAsync()
    Await response.WriteAsync($"{{""code"":1, ""msg"":""JSON 保存成功"",""data"":{bodyJson}}}")
End Function

'处理单层星号通配符 POST 请求
'路由：POST /api/*/posts（匹配 /api/xxx/posts，* 为任意单段路径）
'内置防目录遍历，自动拦截 ../ 等非法字符
Private Shared Async Function HandleWildcardPost(request As HttpListenerRequest, response As HttpListenerResponse) As Task
    Dim requestUrl As String = request.Url.AbsolutePath
    Dim bodyJson As String = Await request.ReadBodyAsStringAsync()
    Dim output As String = $"{{
        ""code"": 1,
        ""msg"": ""通配符路由匹配成功"",
        ""data"": {{
            ""requestUrl"": ""{requestUrl}"",
            ""receivedData"": {bodyJson}
        }}
    }}"
    Await response.WriteAsync(output)
End Function

'处理多层星号通配符 GET 请求
' 路由：GET /api/*/user/*/detail（匹配 /api/xxx/user/yyy/detail，每段一个 *）
Private Shared Async Function HandleMultiWildcard(request As HttpListenerRequest, response As HttpListenerResponse) As Task
    Dim requestUrl As String = request.Url.AbsolutePath
    Dim output As String = $"{{""code"":1,""msg"":""多层通配符匹配成功"",""requestUrl"":""{requestUrl}""}}"
    Await response.WriteAsync(output)
End Function</code></pre>
<p><strong>相关方法</strong></p>
<pre><code class="language-vb">request.GetQuery() '获取指定查询参数，不存在则返回null
request.GetQuery(Of T)() '按类型返回指定查询参数，失败返回类型默认值
request.ParseForm() '获取表单数据
request.ReadBodyAsStringAsync() '获取 body 字符串
request.Items() '获取当前请求的扩展属性字典。用于在不同中间件之间传递和共享数据。【Pro版】</code></pre>
<h2>3.Cookie 增删改查</h2>
<pre><code class="language-vb">Sub Main()
    MyAPI.AddRoute("/cookie/set", AddressOf SetCookie, "GET")
    MyAPI.AddRoute("/cookie/get", AddressOf GetCookie, "GET")
    MyAPI.AddRoute("/cookie/delete", AddressOf DeleteCookie, "GET")
    MyAPI.AddRoute("/cookie/clear", AddressOf ClearCookies, "GET")

    MyAPI.StartServer(8090)
    Console.WriteLine("Cookie 测试服务已启动：http://127.0.0.1:8090")
    Console.ReadKey()
    MyAPI.StopServer()
End Sub

' 设置 Cookie（支持过期时间、路径、HttpOnly）
Private Async Function SetCookie(request As HttpListenerRequest, response As HttpListenerResponse) As Task
    ' 添加普通 Cookie（1小时过期）
    response.AppendCookie("token", "pico_1234567", New CookieOptions With 
    {
            .Expires = DateTimeOffset.Now.AddHours(1),
            .Path = "/",
            .HttpOnly = True ' 防止前端 JS 读取，提升安全性
    })
    ' 添加自定义路径 Cookie
    response.AppendCookie("theme", "dark", New CookieOptions With 
    {
            .Expires = DateTimeOffset.Now.AddDays(7),
            .Path = "/"
    })
    response.BuildCookie() '关键，多个Cookie需进行拼接
    Await response.WriteAsync("{""code"":1, ""msg"":""Cookie 设置成功""}")
End Function

' 读取 Cookie
Private Async Function GetCookie(request As HttpListenerRequest, response As HttpListenerResponse) As Task
    ' 安全读取 Cookie（避免空引用）
    Dim token As String = Nothing
    request.TryGetCookieValue("token", token)
    Dim theme As String = Nothing
    request.TryGetCookieValue("theme", theme)

    Await response.WriteAsync($$"""{{""code"":1, ""token"":""{token}"",""theme"":""{theme}""}}")
End Function

' 删除指定 Cookie
Private Async Function DeleteCookie(request As HttpListenerRequest, response As HttpListenerResponse) As Task
    response.DeleteCookie("token", New CookieOptions With {.Path = "/"})
    Await response.WriteAsync("{""code"":1, ""msg"":""Token Cookie 删除成功""}")
End Function

' 批量清理所有 Cookie
Private Async Function ClearCookies(request As HttpListenerRequest, response As HttpListenerResponse) As Task
    response.ClearCookies()
    Await response.WriteAsync("{""code"":1, ""msg"":""所有 Cookie 已清理""}")
End Function</code></pre>
<h2>4.RESTful 风格路由</h2>
<pre><code class="language-vb">Private ReadOnly MyAPI As New WebAPIServer()

Sub Main()
    MyAPI.AddRoute("/users", AddressOf Users)
    MyAPI.StartServer()
    Console.WriteLine("服务已启动：http://127.0.0.1:8090")
    Console.ReadKey()
    MyAPI.StopServer()
End Sub

Private Async Function Users(request As HttpListenerRequest, response As HttpListenerResponse) As Task
    response.ContentType = GetContentType(".json")
    Select Case request.HttpMethod
        Case "GET"
            Await response.WriteAsync("{""code"":1,""msg"":""获取用户成功"",""data"":{""username"":""PicoServer""}}")
        Case "POST"
            response.StatusCode = 201
            Await response.WriteAsync("{""code"":1,""msg"":""创建用户成功"",""data"":{""userId"":""123456""}}")
        Case Else
            response.StatusCode = 405
            Await response.WriteAsync("{""code"":0,""msg"":""方法不允许""}")
    End Select
End Function</code></pre>
<p><strong>相关方法</strong></p>
<pre><code class="language-vb">GetContentType(".html") '根据文件扩展名获取 MIME 类型：text/html;charset=UTF-8</code></pre>
<p><code>GetContentType</code> 为跨平台通用方法（Windows/Linux/Docker 结果一致），可根据文件扩展名获取标准化 MIME 类型，支持的扩展名有：.html/.htm、.css、.js、.json、.txt、.xml、.jpg/.jpeg、.png、.gif、.webp、.svg/.svgz、.ico、.mp4、.webm、.mp3、.wav、.m3u8、.ts、.woff2、.woff、.ttf、.otf、.pdf、.zip、.rar、.7z、.apk；文本类类型默认带 UTF-8 编码，未知类型返回 application/octet-stream。</p>
<h2>5.特性路由</h2>
<blockquote>
<p>标记特性即可自动注册路由，构建高级应用更爽快。免费版完全支持 AOT ，但特性路由通过扩展包<code>PicoServer.Extensions</code>反射实现，Pro 版特性路由支持 AOT</p>
</blockquote>
<pre><code class="language-vb">&lt;ApiController&gt;
Public Class UserController
    &lt;ApiRoute("/api/user", "GET")&gt;
    Public Async Function GetUser(req As HttpListenerRequest, res As HttpListenerResponse) As Task
        Await res.WriteAsync("{""id"":1,""name"":""张三""}", WebAPIServer.ContentType.ApplicationJson)
    End Function

    &lt;ApiRoute("/api/user", "POST")&gt;
    Public Async Function CreateUser(req As HttpListenerRequest, res As HttpListenerResponse) As Task
        Await res.WriteAsync("{""success"":true}", WebAPIServer.ContentType.ApplicationJson)
    End Function
End Class</code></pre>
<p><strong>相关函数</strong></p>
<pre><code class="language-vb">MyAPI.AutoRegisterRoutes() '自动注册特性路由</code></pre>
<h2>6.静态文件托管</h2>
<blockquote>
<p>静态文件（HTML/CSS/JS/ 图片 / 视频）托管配置，适配前端页面直接访问、静态资源服务等场景。如B/S架构的网站应用</p>
</blockquote>
<pre><code class="language-vb">Friend ReadOnly MyAPI As New WebAPIServer()

Sub Main()
    '添加静态文件服务， wwwroot 目录
    MyAPI.AddStaticFiles("/", "wwwroot")
    MyAPI.AddCors() '允许跨域
    MyAPI.StartServer()
    '保持程序作为服务运行,兼容windows和linux
    Console.WriteLine("服务器已启动，按Ctrl+C退出...")
    Thread.Sleep(Timeout.Infinite)
End Sub</code></pre>
<p><strong>相关函数</strong></p>
<pre><code class="language-vb">'添加静态文件服务。第一个参数为路由，第二个为服务端文件夹（相对/绝对路径），没有匹配到文件则回到路由匹配
MyAPI.AddStaticFiles("/", "wwwroot") '默认开启自动识别缓存
app.AddStaticFiles("/web", "www", 2592000)  ' 缓存30 天
MyAPI.AddCors() '启用跨域</code></pre>
<h2>7.跨域配置</h2>
<blockquote>
<p>解决前后端分离跨域限制，支持极简配置与自定义配置</p>
</blockquote>
<pre><code class="language-vb">MyAPI.AddCors() '启用跨域，默认允许所有来源/方法/请求头
MyAPI.AddCors("picoserver.cn") '支持指定跨域
'更多个性化跨域自定义跨域中间件即可。</code></pre>
<h2>8.文件上传/下载</h2>
<pre><code class="language-vb">Private ReadOnly MyAPI As New WebAPIServer()

Sub Main()
    MyAPI.AddRoute("/file/download", AddressOf DownloadFile, "GET")    ' 文件下载/预览
    MyAPI.AddRoute("/file/upload", AddressOf UploadFile, "POST")       ' 文件上传

    MyAPI.StartServer()
    Console.WriteLine("文件服务已启动：http://127.0.0.1:8090")
    Console.ReadKey()
    MyAPI.StopServer()
End Sub

' 文件下载/预览（asAttachment=false 预览，true 强制下载）
Private Async Function DownloadFile(request As HttpListenerRequest, response As HttpListenerResponse) As Task
    Dim TestFile As String = "D:\test.mp4"
    If Not File.Exists(TestFile) Then
        Await response.WriteAsync("{""code"":0, ""msg"":""文件不存在""}")
        Return
    End If
    Await response.SendFileAsync(TestFile, True)
End Function

' 文件上传（带进度回调）
Private Async Function UploadFile(request As HttpListenerRequest, response As HttpListenerResponse) As Task
    Dim fname As String = request.Headers("filename") '从请求头中获取文件名（test112.mp4），示例为相对位置，中文文件名建议用BASE64编码或者URL编码
    Dim isSuccess As Boolean = Await request.SaveFileAsync(fname, Sub(current, total)
        ' 打印上传进度（百分比）
        Console.WriteLine($"上传进度：{ current * 100 / total}%")
    End Sub)

    If isSuccess Then
        Await response.WriteAsync("{""code"":1, ""msg"":""文件上传成功""}")
    Else
        Await response.WriteAsync("{""code"":0, ""msg"":""文件上传失败""}")
    End If
    Console.WriteLine($"请求头中的文件名：{fname}")
End Function</code></pre>
<p><strong>相关函数</strong></p>
<pre><code class="language-vb">'发送文件，支持断点下载
response.SendFileAsync() '流式发送，大文件低内存消耗，根据扩展名自动添加文件类型
response.SendFileAsync(filePath) '支持文档/视频等直接预览
response.SendFileAsync(filePath,True) '强制下载
response.SendFileAsync(Mp4Path,False,request) '播放视频，支持拖动播放
'接受文件上传，支持断点续传
request.SaveFileAsync() '流式保存，大文件低内存消耗
request.SaveFileAsync(filePath) '保存文件到指定路径（相对/绝对皆可），需要包含文件名
request.SaveFileAsync(filePath,AddressOf onProgress) '保存文件到指定路径，支持回调进度。

request.Headers("filename") '举例：从请求头中获取文件名，生产中应进行非空判断</code></pre>
<h2>9.流媒体/直播流推送</h2>
<pre><code class="language-vb">Private ReadOnly MyAPI As New WebAPIServer()

Sub Main()
    MyAPI.AddRoute("/stream/live", AddressOf LiveStream, "GET") ' 直播流推送
    MyAPI.StartServer()
    Console.WriteLine("流媒体服务已启动：http://127.0.0.1:8090")
    Console.ReadKey()
    MyAPI.StopServer()
End Sub

Private Async Function LiveStream(request As HttpListenerRequest, response As HttpListenerResponse) As Task
    Dim LiveFile As String = "D:\test.mp4" ' 直播源文件（可替换为实时流）
    If Not File.Exists(LiveFile) Then
        Await response.WriteAsync("{""code"":0, ""msg"":""直播源不存在""}")
        Return
    End If

    ' 打开文件流（FileShare.ReadWrite 允许文件被其他程序写入）
    Using fs As New FileStream(LiveFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)
        Await response.SendStreamAsync(fs, GetContentType(".mp4"), True)
    End Using
End Function</code></pre>
<p><strong>相关方法</strong></p>
<pre><code class="language-vb">response.SendStreamAsync(fs, GetContentType(".mp4"), True) '无缓存、Chunked 传输，适配实时流，各种流</code></pre>
<h2>10.简单 Token/JWT 鉴权</h2>
<blockquote>
<p>一旦添加鉴权，默认所有路由都需要鉴权，不需要鉴权的路由需要添加到路由白名单</p>
<p>白名单只针对精准路由（路径），不支持星号路由</p>
</blockquote>
<h4>路由白名单</h4>
<pre><code class="language-vb">MyAPI.RouteWhiteList '储存路由白名单的集合
MyAPI.RouteWhiteList.Add("/api/login") '添加接口到白名单，无需验证</code></pre>
<h4><strong>简单token鉴权</strong></h4>
<pre><code class="language-vb">Private ReadOnly MyAPI As New WebAPIServer()
Private _testToken As String = "PicoServer123" ' 测试用 Token

Sub Main()
    MyAPI.AddRoute("/api/login", AddressOf Login, "POST")
    MyAPI.AddRoute("/api/user/info", AddressOf GetUserInfo, "GET")

    '配置白名单（放行登录接口）
    MyAPI.RouteWhiteList.Add("/api/login")
    MyAPI.AddSimpleTokenVerify(_testToken)

    MyAPI.StartServer()
    Console.WriteLine($"鉴权服务已启动，测试 Token：{_testToken}")
    Console.ReadKey()
    MyAPI.StopServer()
End Sub

' 登录接口（白名单，无需鉴权）
Private Async Function Login(request As HttpListenerRequest, response As HttpListenerResponse) As Task
    Await response.WriteAsync($"{{""code"":1, ""msg"":""登录成功"",""token"":""{_testToken}""}}")
End Function

' 用户信息接口（需鉴权，非白名单）
Private Async Function GetUserInfo(request As HttpListenerRequest, response As HttpListenerResponse) As Task
    Dim token As String = request.GetToken()
    Await response.WriteAsync($"{{""code"":1, ""msg"":""获取信息成功"",""token"":{token}}}")
End Function</code></pre>
<p><strong>相关方法</strong></p>
<pre><code class="language-vb">MyAPI.AddSimpleTokenVerify(testToken) '添加简单 token 验证中间件，参数为token
request.GetToken() '获取请求头中的token值</code></pre>
<h4><strong>JWT鉴权</strong></h4>
<pre><code class="language-vb">Private ReadOnly MyAPI As New WebAPIServer()
Private _testToken As String ' 测试用 Token

Sub Main()
    ' 1. 注册路由（先注册，后配置鉴权）
    MyAPI.AddRoute("/api/login", AddressOf Login, "POST")       ' 白名单路由（无需鉴权）
    MyAPI.AddRoute("/api/user/info", AddressOf GetUserInfo, "GET") ' 需鉴权路由

    ' 2. 配置白名单（放行登录接口）
    MyAPI.RouteWhiteList.Add("/api/login")

    ' 3. 启用 JWT 鉴权（密钥需与生成 Token 时一致）
    MyAPI.AddJwtTokenVerify("pico_secret_779")

    ' 4. 生成测试 Token（模拟登录成功）
    GenerateTestToken()

    MyAPI.StartServer()
    Console.WriteLine($"鉴权服务已启动，测试 Token：{_testToken}")
    Console.ReadKey()
    MyAPI.StopServer()
End Sub

' 简化版：生成测试 JWT Token
Private Sub GenerateTestToken()
    ' 过期时间：当前+1小时（10位时间戳）
    Dim exp As Long = MyAPI.GetTimeStamp10(3600)
    ' 直接使用字符串插值构造载荷，简化代码
    Dim payload As String = $"{{""username"":""admin"",""role"":""super"",""exp"":{exp}}}"
    ' 生成 Token
    _testToken = MyAPI.Jwt.GenerateToken(payload)
End Sub

' 登录接口（白名单，无需鉴权）
Private Async Function Login(request As HttpListenerRequest, response As HttpListenerResponse) As Task
    ' 模拟登录验证（实际场景替换为账号密码校验）
    Await response.WriteAsync($"{{""code"":1, ""msg"":""登录成功"",""token"":""{_testToken}""}}")
End Function

' 用户信息接口（需鉴权，非白名单）
Private Async Function GetUserInfo(request As HttpListenerRequest, response As HttpListenerResponse) As Task
    ' 获取请求头中的 Token 并解析载荷
    Dim token As String = request.GetToken()
    Dim payload As String = MyAPI.Jwt.DecodePayload(token)

    Await response.WriteAsync($"{{""code"":1, ""msg"":""获取信息成功"",""userInfo"":{payload}}}")
End Function</code></pre>
<p><strong>相关方法</strong></p>
<blockquote>
<p>PicoServer.Crypto（Pro版）</p>
</blockquote>
<pre><code class="language-vb">MyAPI.AddJwtTokenVerify("pico_secret_779") '添加 JWT 鉴权中间件，参数为HS256加密密钥
MyAPI.AddJwtTokenVerify("pico_secret_779", PicoServer.Crypto.HashType.SM3) '添加 JWT 鉴权中间件，参数为 HMAC-SM3 加密密钥

request.GetToken() '获取请求头中的token值
MyAPI.Jwt.DecodePayload(token) '解码 JWT 负载为字符串
MyAPI.Jwt.GenerateToken(payload) '创建 JWT token 参数为负载，用于储存信息

MyAPI.GetTimeStamp10(3600) ' 获取10位时间戳，参数：需要追加的秒数，不传入则返回当前时间戳
MyAPI.GetTimeStamp13() ' 获取13位时间戳，参数：需要追加的毫秒数，不传入则返回当前时间戳

' 加密工具（PicoServer.Crypto）
Dim signature As String = HS256.ComputeHmac256(data, key) ' HMAC-SHA256 签名
Dim hash As Byte() = SM3.ComputeHash(data) ' SM3 哈希计算
Dim hmacSm3 As String = SM3.ComputeHmacSM3(data, key) ' HMAC-SM3 签名
Dim passwordHash As String = SM3.HashPassword(password, salt, iterations) ' SM3 密码哈希
Dim encoded As String = Base64Url.Encode(data) ' Base64Url 编码
Dim decoded As String = Base64Url.Decode(encoded) ' Base64Url 解码</code></pre>
<h2>11.SSE服务端推送</h2>
<pre><code class="language-vb">Private ReadOnly MyAPI As New WebAPIServer()

Sub Main()
    MyAPI.AddRoute("/iot/notify", AddressOf Notify, "GET") ' SSE推送
    MyAPI.StartServer(8090)
    Console.WriteLine("SSE推送服务已启动：http://127.0.0.1:8090/iot/notify")
    Console.ReadKey()
    MyAPI.StopServer()
End Sub

' SSE推送消息推送（模拟设备报警）
Public Shared Async Function Notify(request As HttpListenerRequest, response As HttpListenerResponse) As Task
    response.ContentType = "text/event-stream"
    response.Headers.Add("Cache-Control", "no-cache")
    response.SendChunked = True

    Try
        For i As Integer = 0 To 4
            Dim msg As String = $"data: 消息推送 {i} 时间: {DateTime.Now}{vbCrLf}{vbCrLf}"
            Dim buffer As Byte() = System.Text.Encoding.UTF8.GetBytes(msg)
            Await response.OutputStream.WriteAsync(buffer, 0, buffer.Length)
            Await response.OutputStream.FlushAsync()
            Await Task.Delay(1000)
        Next
    Finally
        '在使用 HttpListenerResponse 进行 SSE（Server - Sent Events）推送时，response.Close(); 并不是必须的，但推荐在推送结束后调用它，以确保资源释放和连接正确关闭。
        ' 示例这里是推送结束后调用 response.Close();，确保响应流关闭
        ' 如果是无限推送（如实时设备报警），不要关闭响应，直到客户端断开。
        response.Close()
    End Try
End Function</code></pre>
<p>前端 JavaScript 示例(如果测试时候不能访问，注意开启跨域)</p>
<pre><code class="language-javascript">function startSSE() {
    const source = new EventSource("/iot/notify");
    source.onmessage = function (event) {
        document.getElementById("result").innerHTML += event.data + "&lt;br&gt;";
    };
    source.onerror = function () {
        source.close();
    };
}</code></pre>
<p><strong>PicoServer SSE 在线测试工具</strong> <a href="https://picoserver.cn/tools/ssetest.html">https://picoserver.cn/tools/ssetest.html</a></p>
<h2>12.长连接消息推送</h2>
<pre><code class="language-vb">Private ReadOnly MyAPI As New WebAPIServer()

Sub Main()
    MyAPI.AddRoute("/notify", AddressOf LongConnectionPush, "GET") ' 长连接推送
    MyAPI.StartServer(8090)
    Console.WriteLine("长连接服务已启动：http://127.0.0.1:8090/notify")
    Console.ReadKey()
    MyAPI.StopServer()
End Sub

' 长连接消息推送（模拟设备报警）
Private Async Function LongConnectionPush(request As HttpListenerRequest, response As HttpListenerResponse) As Task
    Try
        ' 循环推送消息（实际场景替换为业务事件触发）
        For i As Integer = 0 To 29
            ' 推送报警消息（低内存）
            Await response.WriteChunkAsync($"设备报警 {i}：温度异常 {DateTime.Now:HH:mm:ss}" &amp; vbCrLf)
            ' 模拟 1 秒推送一次
            Await Task.Delay(1000)
        Next

        ' 推送结束，发送结束标识
        Await response.WriteChunkAsync("推送结束")
    Finally
        ' 示例这里是推送结束后调用 response.Close();，确保响应流关闭
        ' 如果是无限推送（如实时设备报警），不要关闭响应，直到客户端断开。
        response.Close()
    End Try
End Function</code></pre>
<p><strong>相关方法</strong></p>
<pre><code class="language-vb">response.WriteChunkAsync("推送结束") '推送字符串
response.Close() '关闭响应，释放资源 【WriteChunkAsync下必须手动关闭，避免资源泄露】</code></pre>
<h2>13.WebSocket 通信</h2>
<ul>
<li>
<p>场景目标：实现 WebSocket 双向交互，适配实时聊天、设备指令交互等场景</p>
</li>
<li>
<p>核心要点：服务端（enableWebSocket 启用、事件订阅、在线客户端管理、广播消息）、客户端（WebSocketClient 初始化、事件订阅、消息发送）</p>
</li>
<li>
<p>运行测试：服务端启动、客户端连接、双向消息交互、广播消息接收</p>
</li>
</ul>
<blockquote>
<p>WebSocket 服务端可以和 WebAPI 同时存在，且共用端口，共用地址<br />
<strong>WebSocket 在线测试工具 <a href="https://wstool.js.org/">https://wstool.js.org/</a></strong></p>
</blockquote>
<h4>WebSocket 服务端</h4>
<pre><code class="language-vb">Private ReadOnly MyAPI As New WebAPIServer()

Sub Main()
    MyAPI.enableWebSocket = True
    MyAPI.WsOnConnectionChanged = AddressOf WsConnectChanged
    MyAPI.WsOnMessage = AddressOf OnMessageReceived

    MyAPI.StartServer()
    Console.WriteLine("PicoServer WebSocket：http://127.0.0.1:8090")
    Console.ReadKey()
    MyAPI.StopServer()
End Sub

Private Async Function WsConnectChanged(clientId As String, connected As Boolean) As Task
    Await MyAPI.WsBroadcastAsync($"{clientId} {connected}")
End Function

Private Async Function OnMessageReceived(clientId As String, message As String, reply As Func(Of String, Task)) As Task
    Await reply("收到！")
    Dim clients = MyAPI.WsGetOnlineClients()
    For Each client In clients
        Await MyAPI.WsSendToClientAsync(client, $"{clientId}说：{message}")
    Next
End Function</code></pre>
<p><strong>相关方法</strong></p>
<pre><code class="language-vb">MyAPI.enableWebSocket = True '启用WebSocket支持
MyAPI.WsOnConnectionChanged ' 事件：WebSocket客户端连接状态发生变化
MyAPI.WsOnMessage '事件：收到WebSocket客户端发送来的消息
MyAPI.WsBroadcastAsync() '对所有在线客户端广播消息
MyAPI.WsGetOnlineClients '获取在线客户端列表
MyAPI.WsSendToClientAsync(client,message) '给指定客户端发送消息
MyAPI.WsEnableHeartbeat = True '启用 WebSocket 服务端心跳检测，默认false
MyAPI.WsHeartbeatTimeout = 60 '设置 WebSocket 心跳时间，默认30秒
MyAPI.WsMaxConnections = 200 '设置 WebSocket 最大连接数，默认100
MyAPI.WsPingString = "hi" '设置 WebSocket 的ping消息，默认"ping"，不区分大小写</code></pre>
<h4>WebSocket 客户端</h4>
<pre><code class="language-vb">Private wsClient As New WebSocketClient("wss://echo.websocket.org/")

Sub Main()
    ' 订阅核心事件
    AddHandler wsClient.OnConnected, AddressOf OnConnected ' 连接成功
    AddHandler wsClient.OnMessageReceived, AddressOf OnMessageReceived ' 接收消息
    AddHandler wsClient.OnDisconnected, AddressOf OnDisconnected ' 连接断开
    AddHandler wsClient.OnError, AddressOf OnError ' 异常触发
    wsClient.StartConnect()
    Console.ReadKey()
    wsClient.StopConnect()
End Sub

Private Sub OnConnected(sender As Object, e As EventArgs)
    Console.WriteLine("连接成功！")
End Sub

Private Sub OnMessageReceived(sender As Object, message As String)
    Console.WriteLine($"收到消息: {message}")
    wsClient.SendMessageAsync($"hi: {DateTime.Now.ToShortTimeString()}")
End Sub

Private Sub OnDisconnected(sender As Object, e As EventArgs)
    Console.WriteLine("连接已断开！")
End Sub

Private Sub OnError(sender As Object, e As WebSocketErrorEventArgs)
    Console.WriteLine($"错误: {e.ErrorCode}, {e.ErrorMessage}")
End Sub</code></pre>
<p><strong>相关方法</strong></p>
<pre><code class="language-vb">Private wsClient As New WebSocketClient() '实例化WebSocket客户端
Private wsClient As New WebSocketClient("wss://echo.websocket.org/") '实例化WebSocket服务端，支持ws和wss,默认5秒超时
Private wsClient As New WebSocketClient("wss://echo.websocket.org/",10) '自定义超时时间10秒

wsClient.StartConnect() '连接服务端
wsClient.StopConnect()  '断开连接
wsClient.SendMessageAsync(message) '发送消息
wsClient.SendPingAsync() '发送ping消息，默认“ping”
wsClient.SendPingAsync("hi") '发送自定义ping消息</code></pre>
<h2>14.高级用法和中间件</h2>
<blockquote>
<p>PicoServer 开放了 <strong>中间件</strong> ，可以借此进行二次开发、封装、集成解决方案等 。</p>
<p>利用 AddMiddleware() 可开发属于自己的中间件。比如：参数路由，限流，黑名单等等。</p>
</blockquote>
<h3>极简文件服务器</h3>
<pre><code class="language-vb">Imports PicoServer

Dim MyAPI = New WebAPIServer()
Dim rootPath As String = "D:\MyFiles" ' 设定你的物理资源根目录

' 1. 首页：列出所有文件 (简单 WebAPI)
MyAPI.AddRoute("/files", Async Function(req, resp)
    Dim files = Directory.GetFiles(rootPath).Select(Function(f) Path.GetFileName(f))
    Dim html = $"
        &lt;h1&gt;文件清单&lt;/h1&gt;
        &lt;ul&gt;
            {String.Join("", files.Select(Function(f) $"&lt;li&gt;&lt;a href='/view?name={f}'&gt;{f}&lt;/a&gt;&lt;/li&gt;"))}
        &lt;/ul&gt;
        "
    Await resp.WriteAsync(html, WebAPIServer.ContentType.TextHtml)
End Function, "GET")

' 2. 查看/预览：支持视频拖动播放 (利用 asAttachment: false)
MyAPI.AddRoute("/view", Function(req, resp)
    Dim fileName As String = req.ParseGetQueryString("name")
    Dim fullPath As String = Path.Combine(rootPath, fileName)

    ' asAttachment: false 允许浏览器直接播放视频或预览图片
    Return resp.SendFileAsync(fullPath, asAttachment:=False)
End Function, "GET")

' 3. 强制下载：(默认 asAttachment: true)
MyAPI.AddRoute("/download", Function(req, resp)
    Dim fileName As String = req.ParseGetQueryString("name")
    Return resp.SendFileAsync(Path.Combine(rootPath, fileName))
End Function, "GET")

MyAPI.StartServer(8090)
Console.WriteLine("文件服务器已启动: http://127.0.0.1:8090")
Console.ReadKey()</code></pre>
<hr />
<h3>自定义中间件</h3>
<blockquote>
<p>这个示例演示了如何利用自定义中间件的扩展功能实现<strong>动态路由</strong>，在一个逻辑块内完成<strong>路径匹配</strong>、<strong>方法分发</strong>和<strong>请求终结</strong>，从而灵活的自定义各种中间件。<strong>注意：中间件的执行是按添加顺序执行的</strong></p>
</blockquote>
<p><strong>极简动态路由</strong></p>
<pre><code class="language-vb">Imports PicoServer
Imports System.Text.RegularExpressions

Dim MyAPI = New WebAPIServer()

' 【提示】前置鉴权/日志中间件应在此处注册

' 极简动态路由：建议作为最后的处理器
MyAPI.AddMiddleware(Async Function(req, resp)
    ' 匹配 /product/123 这种带 ID 的路径
    Dim match = Regex.Match(req.Url.AbsolutePath, "^/product/(?&lt;id&gt;\d+)$")

    If match.Success Then
        Dim id As String = match.Groups("id").Value

        ' 根据请求方式 (Method) 分发逻辑
        Select Case req.HttpMethod
            Case "GET"
                Await resp.WriteAsync($$"""{"action":"查询商品", "id":{{id}}}""")
            Case "POST"
                Await resp.WriteAsync($$"""{"action":"更新商品", "id":{{id}}, "result":"Success"}""")
            Case Else
                resp.StatusCode = 405
                Await resp.WriteAsync("""{"msg":"不支持的操作"}""")
        End Select

        Return False ' 【核心】匹配成功并处理，返回 false 终结请求，不再走默认路由
    End If

    Return True ' 没匹配上，放行给后续逻辑或 404，如果是自定义路由建议放在最后，且只返回false，不再继续分发。
End Function)

MyAPI.StartServer(8090)
Console.WriteLine("动态路由服务已启动: http://127.0.0.1:8090")
Console.ReadKey()</code></pre>]]></description>
    <pubDate>Tue, 30 Dec 2025 21:52:58 +0800</pubDate>
    <dc:creator>PicoServer</dc:creator>
    <guid>https://docs.picoserver.cn/usage-vbnet.html</guid>
</item>
<item>
    <title>🎨集成案例</title>
    <link>https://docs.picoserver.cn/cases.html</link>
    <description><![CDATA[<blockquote>
<p>将 PicoServer 进行集成、开发扩展包</p>
</blockquote>
<hr />
<h3><strong>🎉<a href="https://picoserver.cn" title="PicoServer官网">PicoServer官网</a></strong></h3>
<blockquote>
<p>采用 nginx 反代 + PicoServer 静态文件托管，无缓存，.NET10 运行在香港 Linux 服务器<br />
<a href="https://picoserver.cn" title="https://picoserver.cn">https://picoserver.cn</a></p>
</blockquote>
<hr />
<h3><strong>🎉<a href="https://www.cnblogs.com/densen2014/p/19670899" title="《MAUI 嵌入式 Web 架构实战》">《MAUI 嵌入式 Web 架构实战》</a></strong></h3>
<blockquote>
<p>一个 MAUI 应用，其实可以变成一个“迷你服务器”。这不仅仅是一个技术实验，而是一种新的架构思路。<br />
— <strong>微软 MVP</strong> <a href="https://www.cnblogs.com/densen2014" title="AlexChow">AlexChow</a><br />
配套开源：<a href="https://github.com/densen2014/MauiPicoAdmin">https://github.com/densen2014/MauiPicoAdmin</a></p>
</blockquote>
<hr />
<h3><strong>🎉<a href="https://www.cnblogs.com/lesliexin/p/19475073" title="（原创）[C#]【开源】一分钟使用 PicoServer 打造日志服务器">（原创）[C#]【开源】一分钟使用 PicoServer 打造日志服务器</a></strong></h3>
<blockquote>
<p>开源地址：<a href="https://gitee.com/lesliexin/lesliexin.simplelogservice">https://gitee.com/lesliexin/lesliexin.simplelogservice</a></p>
</blockquote>
<hr />
<h3><strong>🎉微型嵌入式 Linux 采集网关【企业项目】</strong></h3>
<blockquote>
<p>得益于 .NET 10 的跨平台能力与 AOT 编译支持，开发者利用 PicoServer 的轻量优势，在 64MB 内存的微型 Linux 系统中构建了采集网关的 Web 配置后台，提供静态页面托管与设备管理接口，整个程序内存占用不超过5M。</p>
</blockquote>
<hr />
<h3><strong>🎉SQLToWebAPI【商业项目】</strong></h3>
<blockquote>
<p>通过编写SQL语句即可快速生成RESTful API接口，无需编写复杂的后端代码。完整的TOKEN认证系统，支持API级别的权限控制和白名单功能，现代化的Web管理界面，支持中英文双语，提供完整的API管理功能。<br />
📊 API日志记录 📦 批量导入导出 📈 实时统计分析 🎯 Top 10 API</p>
</blockquote>
<hr />
<h3><strong>🎉<a href="https://admin.picoserver.cn" title="工控 Web 管理后台">工控 Web 管理后台示例</a></strong></h3>
<blockquote>
<p>B/S架构示例，JWT鉴权 + 静态文件托管 + WebAPI 同时可用。<br />
<a href="https://admin.picoserver.cn" title="https://admin.picoserver.cn">https://admin.picoserver.cn</a></p>
</blockquote>
<hr />]]></description>
    <pubDate>Tue, 09 Dec 2025 21:33:10 +0800</pubDate>
    <dc:creator>PicoServer</dc:creator>
    <guid>https://docs.picoserver.cn/cases.html</guid>
</item>
<item>
    <title>🎖️性能测试</title>
    <link>https://docs.picoserver.cn/benchmark.html</link>
    <description><![CDATA[<h3>💖 测试说明</h3>
<blockquote>
<p>测试报告基于 PicoServer <strong>开箱即用、未做任何性能调优</strong> 的状态，在真实办公环境下完成压测，实际运行性能受当前系统 CPU 主频、电源策略、后台进程负载、.NET 运行时版本、编译模式等多因素影响，理性看待。测试工具采用 <a href="https://github.com/rakyll/hey">hey</a>。<br />
<strong>开发者基准</strong>数据可作为开发者<strong>本地参考、线下环境对比、生产部署预估</strong>的参考。</p>
</blockquote>
<h3>🖥️ 测试环境</h3>
<table>
<thead>
<tr>
<th>设备</th>
<th>处理器</th>
<th>内存</th>
<th>系统</th>
<th>运行时</th>
<th>供电</th>
</tr>
</thead>
<tbody>
<tr>
<td>开发笔记本</td>
<td>Core Ultra 5 125H (1.20GHz)</td>
<td>24GB</td>
<td>Windows 11</td>
<td>.NET 10 / .NET FX 4.7.2</td>
<td>电池模式</td>
</tr>
<tr>
<td>入门台式机</td>
<td>i3-10105 @ 3.70GHz</td>
<td>8GB</td>
<td>Windows 10</td>
<td>.NET 10</td>
<td>插电</td>
</tr>
</tbody>
</table>
<h3>📊 测试命令</h3>
<pre><code class="language-bash"># 100 并发短时压力
hey -n 50000 -c 100 http://127.0.0.1:8090

# 50 并发长稳测试
hey -c 50 -z 15s http://127.0.0.1:8090</code></pre>
<p><strong>预期响应</strong>：</p>
<pre><code class="language-json">{"code": 1, "msg": "Hello PicoServer"}</code></pre>
<h3>📈 测试结果</h3>
<h4>🚀 轻量接口请求</h4>
<p>小体量纯 JSON 接口</p>
<table>
<thead>
<tr>
<th>设备</th>
<th>运行时</th>
<th>QPS</th>
<th>平均延迟</th>
<th>P99 延迟</th>
<th>错误率</th>
</tr>
</thead>
<tbody>
<tr>
<td>开发笔记本</td>
<td>.NET FX 4.7.2</td>
<td>55118</td>
<td>1.3ms</td>
<td>5.3ms</td>
<td>0%</td>
</tr>
<tr>
<td>开发笔记本</td>
<td>.NET 10</td>
<td>43000</td>
<td>2.3ms</td>
<td>6.2ms</td>
<td>0%</td>
</tr>
<tr>
<td>入门台式机</td>
<td>.NET 10</td>
<td>40600</td>
<td>2.4ms</td>
<td>3.3ms</td>
<td>0%</td>
</tr>
</tbody>
</table>
<h4>📄 常规资源请求</h4>
<p>内嵌页面资源，响应 56KB HTML</p>
<table>
<thead>
<tr>
<th>设备</th>
<th>运行时</th>
<th>QPS</th>
<th>平均延迟</th>
<th>P99 延迟</th>
<th>错误率</th>
</tr>
</thead>
<tbody>
<tr>
<td>开发笔记本</td>
<td>.NET 10</td>
<td>20100</td>
<td>4.7ms</td>
<td>7.1ms</td>
<td>0%</td>
</tr>
<tr>
<td>入门台式机</td>
<td>.NET 10</td>
<td>17100</td>
<td>5.8ms</td>
<td>≈7ms</td>
<td>0%</td>
</tr>
</tbody>
</table>
<h4>⏱️ 持续稳定性测试</h4>
<p>50 并发，持续 15 秒</p>
<table>
<thead>
<tr>
<th>设备</th>
<th>运行时</th>
<th>QPS</th>
<th>平均延迟</th>
<th>总请求量</th>
<th>错误率</th>
</tr>
</thead>
<tbody>
<tr>
<td>开发笔记本</td>
<td>.NET FX 4.7.2</td>
<td>69487</td>
<td>1.9ms</td>
<td>100万+</td>
<td>0%</td>
</tr>
<tr>
<td>入门台式机</td>
<td>.NET 10</td>
<td>17400</td>
<td>1.9ms</td>
<td>261000+</td>
<td>0%</td>
</tr>
<tr>
<td>开发笔记本</td>
<td>.NET 10</td>
<td>14200</td>
<td>1.9ms</td>
<td>206000+</td>
<td>0%</td>
</tr>
</tbody>
</table>
<h3>✨ 关键亮点</h3>
<ol>
<li><strong>高性能</strong>：轻量接口稳定基准 <strong>55118 QPS</strong>，峰值可达 <strong>76716 QPS</strong>；常规请求稳定 <strong>1.7 万+ QPS</strong>。CPU 主频与供电策略会直接影响并发上限，笔记本电池模式存在性能约束。</li>
<li><strong>低门槛部署</strong>：8GB 入门配置即可稳定运行，全场景 <strong>零错误</strong>，P99 延迟维持在个位数毫秒。生产环境可通过减少后台冗余进程，进一步降低性能波动。</li>
<li><strong>资源极简</strong>：高负载 CPU 占用 <strong>＜7%</strong>，内存常驻约 <strong>16MB</strong>，无内存泄漏，适合低配置服务器、边缘设备、轻量化部署场景。</li>
<li><strong>双编译支持</strong>：同时支持 JIT 与 AOT 编译：JIT 稳态吞吐更强，AOT 冷启动更快、跨环境性能统一，可按需选用。</li>
</ol>
<h3>🍑 生产说明</h3>
<blockquote>
<p>本文档所有基准数据均为线下办公环境实测，未经过服务器级优化。实际运行表现受软硬件环境影响，建议上线前在目标环境自行压测验证。</p>
</blockquote>
<h3>🛠️ 压测工具</h3>
<p>测试使用 <a href="https://github.com/rakyll/hey">hey</a> HTTP 负载测试工具。</p>
<p>:::tip[蓝奏云下载]<br />
<a href="https://wwbgk.lanzouu.com/iRvB43f4e01i">https://wwbgk.lanzouu.com/iRvB43f4e01i</a> 密码:bqnu<br />
:::</p>]]></description>
    <pubDate>Thu, 04 Dec 2025 23:50:15 +0800</pubDate>
    <dc:creator>PicoServer</dc:creator>
    <guid>https://docs.picoserver.cn/benchmark.html</guid>
</item>
<item>
    <title>📌更新日志</title>
    <link>https://docs.picoserver.cn/update.html</link>
    <description><![CDATA[<blockquote>
<p><strong>PicoServer</strong> 作为 <strong>Web 能力胶水库</strong>，以轻量级 HTTP 服务器核心基础能力为支撑，提供<strong>开箱即用和灵活扩展</strong>的能力，兼容跨平台与 AOT 编译。<br />
<strong>推荐使用 PicoServer 最新版本，保障功能完整性,极简设计，没有破坏性更新，可放心升级</strong><br />
数字版本号为免费版，免费可商用。日期版本号为 Pro 版，Pro 版本包含免费版所有功能。</p>
</blockquote>
<h2>V1.7.2</h2>
<ul>
<li>🛠️ 优化时间戳方法<code>GetTimeStamp13</code>和<code>GetTimeStamp10</code>，统一使用四舍五入法，确保跨项目行为一致。并优化性能。</li>
</ul>
<h2>V1.7.1</h2>
<ul>
<li>🐛 修复 <code>WsMaxConnections</code> 和 <code>enableWebSocket</code> 无效的bug</li>
</ul>
<h2>Pro v2026.4.25</h2>
<ul>
<li>🐛 修复 <code>WsMaxConnections</code> 和 <code>enableWebSocket</code> 无效的bug</li>
<li>🛠️ 增强 <code>websocket</code> 广播性能，实测 10000 连接，服务端 398mb 内存，客户端 172mb 内存。</li>
</ul>
<h2>V1.7</h2>
<ul>
<li>➕ <code>WebAPIServer</code> 主类增加 <code>MapGet</code>、<code>MapPost</code>、<code>MapPut</code>、<code>MapDelete</code> 四个语义化方法，封装于 <code>AddRoute</code> 基础方法，提升开发体验</li>
</ul>
<h2>Pro v2026.4.16</h2>
<p><strong> 🔐 加密增强</strong></p>
<ul>
<li>➕ 内置 JWT 验证新增国密 HMAC-SM3 签名和验证</li>
<li>➕ 新增 <code>PicoServer.Crypto</code> 命名空间，统一提供内置算法</li>
</ul>
<p><strong> 📦 新增 API</strong></p>
<table>
<thead>
<tr>
<th>方法</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>HS256.ComputeHmac256</code></td>
<td>HMAC-SHA256 签名</td>
</tr>
<tr>
<td><code>SM3.ComputeHash</code></td>
<td>SM3 哈希计算</td>
</tr>
<tr>
<td><code>SM3.ComputeHmacSM3</code></td>
<td>HMAC-SM3 签名（JWT 国密支持）</td>
</tr>
<tr>
<td><code>SM3.HashPassword</code></td>
<td>基于 SM3 的密码哈希（带迭代拉伸）</td>
</tr>
<tr>
<td><code>Base64Url.Encode</code></td>
<td>Base64Url 编码（URL 安全）</td>
</tr>
<tr>
<td><code>Base64Url.Decode</code></td>
<td>Base64Url 解码（URL 安全）</td>
</tr>
</tbody>
</table>
<p>📚 详细文档</p>
<ul>
<li><strong>C# 使用指南</strong>：<a href="https://docs.picoserver.cn/usage-csharp.html">https://docs.picoserver.cn/usage-csharp.html</a></li>
<li><strong>VB.NET 使用指南</strong>：<a href="https://docs.picoserver.cn/usage-vbnet.html">https://docs.picoserver.cn/usage-vbnet.html</a></li>
</ul>
<h2>V1.6.5</h2>
<ul>
<li>➕ <code>AddStaticFiles</code>（静态文件托管中间件）增加内置缓存功能。采用文件指纹自动校验，确保文件变更时同步更新，同时支持设置强缓存时长，测试和生产环境无缝切换。</li>
</ul>
<h2>Pro v2026.4.5</h2>
<ul>
<li>➕ <code>StartServer</code> 新增监听指定 IP 的重载功能。支持锁定本地回环（127.0.0.1）或内网地址，有效解决安卓 App 本地服务权限收敛及云服务器部署时的边界安全问题，防止私有数据意外暴露。</li>
</ul>
<h2>Pro v2026.3.10</h2>
<p>🚀 特性路由（Attribute Routing）</p>
<ul>
<li>➕ 支持通过特性自动注册路由，构建高级应用更爽快</li>
<li>➕ 新增 <code>[ApiController]</code> 和 <code>[ApiRoute]</code> 特性，标记特性即可自动注册路由</li>
</ul>
<p>📝 使用示例</p>
<pre><code class="language-csharp">[ApiController]
public class UserController
{
    [ApiRoute("/api/user", "GET")]
    public async Task GetUser(HttpListenerRequest req, HttpListenerResponse res)
    {
        // 处理 GET 请求
    }

    [ApiRoute("/api/user", "POST")]
    public async Task CreateUser(HttpListenerRequest req, HttpListenerResponse res)
    {
        // 处理 POST 请求
    }
}</code></pre>
<p>⚡ 特性路由 AOT 支持策略</p>
<table>
<thead>
<tr>
<th>版本</th>
<th>AOT 支持</th>
<th>特性路由功能</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>免费版（核心库）</strong></td>
<td>✅ 支持</td>
<td>不包含</td>
</tr>
<tr>
<td><strong>免费版 + 扩展包</strong></td>
<td>❌ 不支持</td>
<td>可用特性路由</td>
</tr>
<tr>
<td><strong>Pro 版</strong></td>
<td>✅ 支持</td>
<td>内置特性路由</td>
</tr>
</tbody>
</table>
<blockquote>
<p>💡 免费版核心库支持 AOT，扩展包 <code>PicoServer.Extensions</code>（按需安装）不影响自包含但会破坏 AOT。如需 AOT + 特性路由，请使用 Pro 版。</p>
</blockquote>
<h2>Pro v2026.2.23</h2>
<ul>
<li>➕ 增加 HTTP 请求下文同步功能，单请求中可通过 <code>items</code> 字典储存并共享数据。</li>
</ul>
<h2>V1.6.4</h2>
<ul>
<li>🛠️ 优化，进一步增强 <code>AddStaticFiles</code> 静态文件托管中间件原生跨平台安全性，默认即安全，禁止访问隐藏文件 (如 .env, .git, .config)</li>
</ul>
<h2>V1.6.3</h2>
<ul>
<li>🛠️ 优化 <code>AddStaticFiles</code> 中间件逻辑，没有匹配到文件则回到路由匹配，去掉多余参数。</li>
<li>➕ <code>AddStaticFiles</code> 中间件新增自动 url 解码，可支持中文等路径。</li>
</ul>
<h2>V1.6.2</h2>
<ul>
<li>➕ Jwt 验证中间件 <code>AddJwtTokenVerify</code> 新增自动验证 exp 字段。内置方法 <code>GetTimeStamp10()</code> 可方便的设置 exp 时间戳</li>
</ul>
<h2>V1.6.1</h2>
<ul>
<li>🛠️ 优化 WebSocket 服务端订阅事件参数的语义化，适配 VS 自动生成参数的场景，提升开发体验。</li>
<li>🛠️ 公开 <code>GetContentType</code> 方法，支持开发者直接调用该方法，根据文件扩展名获取对应的 MIME 类型字符串。如：<code>GetContentType(".html")</code></li>
</ul>
<h2>V1.6</h2>
<ul>
<li>🚀 概念升华：<span style="color:red;"><strong>.NET 应用 + PicoServer = Web 化应用</strong></span><br />
工控上位机 + PicoServer = 可远程管理的 Web 化上位机<br />
桌面应用 + PicoServer = 带 API 接口的桌面服务<br />
控制台程序 + PicoServer = 轻量独立 Web 服务<br />
边缘设备端 + PicoServer = 具备 Web 能力的边缘节点<br />
<span style="color:red;">你的程序 + PicoServer = ？</span></li>
<li>🛠️ 若干细节优化</li>
</ul>
<h2>V1.5.10</h2>
<ul>
<li>➕ 新增 内置静态文件服务器中间件 <code>AddStaticFiles</code>，兼容 B/S 架构下 Web 前端与 WebAPI 接口共存（示例：<code>MyAPI.AddStaticFiles("/", "wwwroot", "/api/")</code>）</li>
<li>🛠️ 优化 <strong>response</strong> 对象的 <code>SendFileAsync</code> 方法：asAttachment 参数默认值改为 False，默认不强制下载文件。</li>
</ul>
<h2>V1.5.9</h2>
<ul>
<li>➕ 新增 内置跨域资源共享（CORS）中间件 <code>AddCors()</code>，适配多场景跨域需求，Web开发更方便：
<ul>
<li>无参调用：自动匹配请求的前端域名（仅允许发起请求的前端地址跨域）；</li>
<li>传参调用：仅放行指定的前端地址（如 <code>AddCors("http://127.0.0.1:5500")</code>）。</li>
</ul></li>
<li>➖ 移除 响应对象（response）的 <code>EnableCors</code> 独立方法：跨域场景需全局中间件处理（而非单个响应调用），该方法无实际使用场景。</li>
</ul>
<h2>V1.5.7</h2>
<ul>
<li>➕ 新增：自动处理 HTTP OPTIONS 跨域预检请求（返回 204 标准响应）</li>
</ul>
<h2>V1.5.6</h2>
<ul>
<li>🛠️ 增强内置 JWT 中间件的稳定性和安全性</li>
</ul>
<h2>V1.5.5</h2>
<ul>
<li>🛠️ 优化 AOT 编译支持。</li>
<li>🛠️ 再次优化性能，星号匹配速度更快，token验证更快，内存占用更低。</li>
<li>🐛 修复 获取url查询中的中文参数值可能出现的乱码。统一为UTF8。</li>
</ul>
<h2>V1.5.4</h2>
<ul>
<li>➕ NuGet 包添加 XML 注释，完善 IDE 智能提示（IntelliSense），提升开发效率。</li>
<li>➕ <strong>request</strong> 对象新增 <code>GetQuery</code> <code>GetQuery(Of T)</code> <code>ParseForm</code> <code>ParseQuery</code> <code>ReadBodyAsStringAsync</code> <code>ReadBodyAsString</code> 六个扩展方法，简化 GET 查询参数、POST 表单参数的获取与解析。</li>
</ul>
<h2>V1.5.3</h2>
<ul>
<li>➕ 为了增加辨识度和长远发展，<strong>MicroServer 正式更名为 PicoServer</strong>，仅名字和根命名空间不同，其余完全一样，只需要替换命名空间为 <a href="https://www.nuget.org/packages/PicoServer">PicoServer</a> 即可完成切换 **。</li>
<li>❤ 官网升级为顶级域名 <a href="http://picoserver.cn" title="picoserver.cn">picoserver.cn</a> ❤ 感谢大家的喜爱和支持。</li>
</ul>
<h2>V1.5.2</h2>
<ul>
<li>➕ <strong>response</strong>对象添加跨域支持方法 <code>EnableCors</code> ，默认*，支持设置单个域名。 由<a href="https://www.cnblogs.com/densen2014" title="AlexChow">Alex Chow</a>提供</li>
</ul>
<h2>V1.5.1</h2>
<ul>
<li>🛠️ 优化星号匹配、内置简单token、JWT验证的速度，性能再次大幅提升</li>
</ul>
<h2>V1.5.0</h2>
<ul>
<li>
<p>➕ 路由新增<code>*</code>通配符支持(内置防目录遍历)，支持多个，但每段url只支持一个。 实现 <code>/api/✳/posts</code> 格式 POST 路由，支持匹配 <code>/api/xxx/posts</code> 单层通配符请求</p>
</li>
<li>
<p>🛠️ 优化路由内部结构和匹配逻辑，性能大幅提升。</p>
</li>
</ul>
<h2>V1.4.6</h2>
<ul>
<li>🛠️ 路由值统一不区分大小写，自动转换为小写来储存和匹配。</li>
</ul>
<h2>V1.4.5</h2>
<ul>
<li>➕ 新增 <code>IsRunning</code> 属性，作为 <strong>服务重启</strong> 判断依据，实现主程序不退出情况下的服务安全启停切换。</li>
<li>🐛 修复 关闭服务后无法再重启服务产生的异常 感谢<a href="https://www.cnblogs.com/densen2014" title="AlexChow">Alex Chow</a>反馈</li>
</ul>
<h2>V1.4.4</h2>
<ul>
<li>➕ 增加对Cookie操作的扩展方法（支持添加、删除、过期等功能），由<a href="https://www.cnblogs.com/densen2014" title="AlexChow">Alex Chow</a>提供。</li>
<li>🐛 优化了C#调用库可能引发的问题</li>
</ul>]]></description>
    <pubDate>Wed, 03 Dec 2025 22:10:01 +0800</pubDate>
    <dc:creator>PicoServer</dc:creator>
    <guid>https://docs.picoserver.cn/update.html</guid>
</item>
</channel>
</rss>