当前位置:首页 > 技术 > 正文内容

在WinForms应用中集成HTTP与WebSocket服务

访客 技术 2026年6月29日 1

创建支持HTTP和WebSocket通信的桌面应用程序

本文介绍如何在 .NET WinForms 项目中同时实现 HTTP 接口和 WebSocket 服务,使传统桌面程序具备网络通信能力,可被外部系统通过标准协议调用或实时交互。

1. 创建 WinForms 项目

使用 Visual Studio 新建一个 Windows Forms 应用(.NET Framework 或 .NET)。项目创建完成后,即可开始添加网络功能模块。

2. 实现轻量级HTTP服务器

利用 HttpListener 类构建内嵌 HTTP 服务,无需依赖 IIS。以下为封装后的服务类:

using System;
using System.Collections.Generic;
using System.Net;
using System.Text;
using System.Threading.Tasks;

public class EmbeddedHttpServer
{
    private readonly HttpListener _listener = new HttpListener();
    private readonly Dictionary<string, Func<HttpListenerContext, Task<string>>> _routes;

    public EmbeddedHttpServer(string[] prefixes)
    {
        if (!HttpListener.IsSupported)
            throw new PlatformNotSupportedException("当前操作系统不支持内建HTTP服务");

        foreach (var prefix in prefixes)
            _listener.Prefixes.Add(prefix);

        _routes = new Dictionary<string, Func<HttpListenerContext, Task<string>>>();
    }

    public void Start()
    {
        _listener.Start();
        ListenForRequests();
    }

    public void Stop()
    {
        _listener.Stop();
        _listener.Close();
    }

    public void MapEndpoint(string path, Func<HttpListenerContext, Task<string>> handler)
    {
        _routes[path] = handler;
    }

    private async void ListenForRequests()
    {
        while (_listener.IsListening)
        {
            try
            {
                var context = await _listener.GetContextAsync();
                _ = HandleRequestAsync(context);
            }
            catch (ObjectDisposedException)
            {
                break;
            }
            catch (Exception ex)
            {
                // 可选:记录异常日志
            }
        }
    }

    private async Task HandleRequestAsync(HttpListenerContext ctx)
    {
        var path = ctx.Request.Url.AbsolutePath;
        var method = ctx.Request.HttpMethod;

        string responseText = "{\"error\":\"未找到匹配接口\"}";
        int statusCode = 404;

        if (_routes.TryGetValue(path, out var handler) && method == "POST")
        {
            responseText = await handler(ctx);
            statusCode = 200;
        }

        var buffer = Encoding.UTF8.GetBytes(responseText);
        ctx.Response.StatusCode = statusCode;
        ctx.Response.ContentType = "application/json; charset=utf-8";
        ctx.Response.ContentLength64 = buffer.Length;
        await ctx.Response.OutputStream.WriteAsync(buffer, 0, buffer.Length);
        ctx.Response.Close();
    }
}

3. 集成WebSocket服务

通过 NuGet 安装 WebSocketSharp-NetStandard 包(版本 1.0.1),用于提供双向通信能力。

4. 构建WebSocket服务管理器

定义统一入口来控制 WebSocket 服务生命周期:

using WebSocketSharp.Server;

public class WsServiceManager
{
    private static WebSocketServer _server;

    static WsServiceManager()
    {
        _server = new WebSocketServer(8888);
        _server.AddWebSocketService<MessageHandler>("/echo");
    }

    public static bool IsRunning => _server?.IsListening == true;

    public static void Launch()
    {
        _server.Start();
    }

    public static void Shutdown()
    {
        _server.Stop();
    }
}

5. 定义消息处理行为

继承 WebSocketBehavior 实现具体业务逻辑:

using WebSocketSharp;
using WebSocketSharp.Server;

public class MessageHandler : WebSocketBehavior
{
    protected override void OnOpen()
    {
        Send("连接已建立");
    }

    protected override void OnMessage(MessageEventArgs e)
    {
        var reply = e.Data switch
        {
            "ping" => "pong",
            _ => $"收到: {e.Data}"
        };
        Send(reply);
    }

    protected override void OnClose(CloseEventArgs e)
    {
        // 连接关闭时清理资源
    }
}

6. 在主窗体中初始化服务

Form1 的构造函数中启动各项服务:

public partial class Form1 : Form
{
    private EmbeddedHttpServer _httpServer;

    public Form1()
    {
        InitializeComponent();
        InitializeServices();
    }

    private void InitializeServices()
    {
        // 启动HTTP服务
        _httpServer = new EmbeddedHttpServer(new[] { "http://127.0.0.1:1314/" });
        _httpServer.MapEndpoint("/api/data", ProcessDataRequest);
        _httpServer.Start();

        // 启动WebSocket服务
        WsServiceManager.Launch();
    }

    private async Task<string> ProcessDataRequest(HttpListenerContext ctx)
    {
        using var reader = new StreamReader(ctx.Request.InputStream, ctx.Request.ContentEncoding);
        var body = await reader.ReadToEndAsync();

        return "{\"status\":\"success\",\"data\":\"操作完成\"}";
    }

    protected override void Dispose(bool disposing)
    {
        if (disposing)
        {
            _httpServer?.Stop();
            WsServiceManager.Shutdown();
        }
        base.Dispose(disposing);
    }
}

7. 测试WebSocket客户端

使用 HTML 页面测试连接:

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>WebSocket 测试</title>
</head>
<body>
  <button onclick="connect()">连接服务器</button>
  <script>
    function connect() {
      const ws = new WebSocket("ws://localhost:8888/echo");
      ws.onopen = () => {
        console.log("连接成功");
        ws.send("Hello Server!");
      };
      ws.onmessage = (event) => {
        console.log("返回:", event.data);
      };
      ws.onclose = () => {
        alert("连接断开");
      };
    }
  </script>
</body>
</html>

相关文章

Linux crontab 详解

1) crontab 是什么cron 是 Linux 的定时任务守护进程;crontab 是用来编辑/查看“按时间周期执行命令”的表(cron table)。常见两类:用户 crontab:每个用户一份(crontab -e 编辑)系统级 crontab / cron.d:可指定执行用户(/etc/crontab、/etc/cron.d/*)2) crontab 时间...

富文本里可以允许的 HTML 属性

一、所有标签默认允许的安全属性(极少)class        (可选)id           (通常建议禁用)title️ 注意:id 容易被滥用做锚点注入,很多系统直接禁用class 允许的话最好只允许固定前缀(如 editor-*)二、a 标签允许属性<a href="" t...

Mac 安装 Node.js 指南

方法一:通过官网安装包(最简单,适合初学者)如果你只是想快速安装并开始使用,这是最直接的方法。访问 Node.js 官网。页面会显示两个版本:LTS (Recommended For Most Users):长期支持版,最稳定。建议选这个。Current:最新特性版,包含最新功能但可能不够稳定。下载 .pkg 安装包并运行。按照安装向导点击“下一步”即可完成。方法二:使用 Homebrew 安装(...

Dom\HTML_NO_DEFAULT_NS 的副作用:自动加闭合标签

在使用Dom\HTMLDocument时,Dom\HTML_NO_DEFAULT_NS 将禁止在解析过程中设置元素的命名空间, 此设置是为了与DOMDocument向后兼容而存在的。当使用它时,已知的一个副作用就是:自动加闭合标签例如 </img> 为什么会这样?当你使用:Dom\HTML_NO_DEFAULT_NS文档会变成 无命名空间模式,此时内部更接近 XML...

Laravel 事件和监听器创建

在 Laravel 中,使用 Artisan 命令创建 Events(事件) 和 Listeners(监听器) 是非常高效的。你可以通过以下几种方式来实现:1. 手动创建单个 Event如果你只想创建一个事件类,可以使用 make:event 命令:Bashphp artisan make:event UserRegistered执行后,文件将生成在 app/Even...

自定义域名解析神器 dnsmasq

什么是 dnsmasq?dnsmasq 是一个轻量级、功能强大的网络服务工具,专为小型和中等规模网络设计。它是一个综合的网络基础设施解决方案[1]。dnsmasq 能做什么?功能说明应用场景DNS 转发与缓存将 DNS 查询转发到上游服务器(ISP、Google DNS 等),并在本地缓存结果加快 DNS 查询速度,减少外部 DNS 流量本地 DNS解析本地网络设备的主机名,无需编辑&n...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。