C# WinForm 程序中实现一个简易的 HTTP 服务器,能够处理 JSON 格式的 GET 和 POST 请求,这是一个很实用的需求,尤其适合做本地调试或轻量级服务。
实现思路
我会基于.NET自带的HttpListener类来实现这个 HTTP 服务器,它可以让 WinForm 程序监听指定端口并处理 HTTP 请求。核心步骤包括:
-
1、初始化
HttpListener并配置监听地址 -
2、异步监听并处理客户端请求
-
3、区分 GET/POST 请求类型
-
4、解析 / 响应 JSON 格式数据
-
5、在 WinForm 界面中控制服务器的启动和停止
完整代码实现
以下是一个开箱即用的 WinForm 程序代码,包含 UI 交互和完整的 HTTP 服务逻辑:
1. 首先是 Form1 的设计(Form1.Designer.cs 核心部分)
using System;using System.IO;using System.Net;using System.Text;using System.Threading;using System.Windows.Forms;// 仅保留Newtonsoft.Json引用using Newtonsoft.Json; namespace WinFormHttpServer{ public partial class Form1 : Form { private HttpListener _httpListener; private Thread _listenerThread; private bool _isListening; // 测试用的实体类 public class UserInfo { public int Id { get; set; } public string Name { get; set; } public string Email { get; set; } } public Form1() { InitializeComponent(); } #region 按钮事件(无修改) private void btnStart_Click(object sender, EventArgs e) { try { int port; if (!int.TryParse(txtPort.Text.Trim(), out port) || port < 1 || port > 65535) { MessageBox.Show("请输入有效的端口号(1-65535)", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } _httpListener = new HttpListener(); _httpListener.Prefixes.Add($"http://*:{port}/"); _httpListener.Start(); _isListening = true; _listenerThread = new Thread(ListenForRequests); _listenerThread.IsBackground = true; _listenerThread.Start(); btnStart.Enabled = false; btnStop.Enabled = true; txtPort.Enabled = false; Log($"服务器已启动,监听地址:http://localhost:{port}/"); } catch (Exception ex) { Log($"启动失败:{ex.Message}"); MessageBox.Show($"启动失败:{ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); } } private void btnStop_Click(object sender, EventArgs e) { StopServer(); } private void Form1_FormClosing(object sender, FormClosingEventArgs e) { StopServer(); } #endregion #region 核心服务逻辑(无修改) private void StopServer() { if (_isListening) { _isListening = false; _httpListener?.Stop(); _listenerThread?.Join(1000); btnStart.Enabled = true; btnStop.Enabled = false; txtPort.Enabled = true; Log("服务器已停止"); } } private void ListenForRequests() { while (_isListening) { try { var context = _httpListener.GetContext(); new Thread(() => ProcessRequest(context)).Start(); } catch (HttpListenerException) { break; } catch (Exception ex) { Log($"请求处理异常:{ex.Message}"); } } } private void ProcessRequest(HttpListenerContext context) { var request = context.Request; var response = context.Response; try { Log($"收到请求 - 方法:{request.HttpMethod},路径:{request.Url.PathAndQuery}"); string responseString = ""; if (request.HttpMethod == "GET") { var user = new UserInfo { Id = 1, Name = "测试用户", Email = "test@example.com" }; // 调用修正后的序列化方法 responseString = SerializeToJson(user); } else if (request.HttpMethod == "POST") { string requestJson = ReadRequestData(request); Log($"POST请求内容:{requestJson}"); var user = DeserializeFromJson<UserInfo>(requestJson); if (user != null) { user.Name = $"处理后的{user.Name}"; responseString = SerializeToJson(new { Success = true, Message = "POST请求处理成功", Data = user }); } else { responseString = SerializeToJson(new { Success = false, Message = "JSON格式错误" }); } } else { responseString = SerializeToJson(new { Success = false, Message = $"不支持的请求方法:{request.HttpMethod}" }); response.StatusCode = (int)HttpStatusCode.MethodNotAllowed; } // 编码控制在这里(UTF8),而非序列化配置中 response.ContentType = "application/json; charset=utf-8"; response.ContentEncoding = Encoding.UTF8; byte[] buffer = Encoding.UTF8.GetBytes(responseString); response.ContentLength64 = buffer.Length; using (var output = response.OutputStream) { output.Write(buffer, 0, buffer.Length); } Log($"响应发送完成:{responseString}"); } catch (Exception ex) { Log($"处理请求异常:{ex.Message}"); string errorJson = SerializeToJson(new { Success = false, Message = ex.Message }); byte[] errorBuffer = Encoding.UTF8.GetBytes(errorJson); response.StatusCode = (int)HttpStatusCode.InternalServerError; response.ContentType = "application/json; charset=utf-8"; response.ContentLength64 = errorBuffer.Length; using (var output = response.OutputStream) { output.Write(errorBuffer, 0, errorBuffer.Length); } } finally { response.Close(); } } #endregion #region 辅助方法(修复Encoding错误) /// <summary> /// 读取请求体数据 /// </summary> private string ReadRequestData(HttpListenerRequest request) { using (var reader = new StreamReader(request.InputStream, request.ContentEncoding)) { return reader.ReadToEnd(); } } /// <summary> /// 修复:移除了错误的Encoding配置,保留其他有用配置 /// </summary> private string SerializeToJson(object obj) { var settings = new JsonSerializerSettings { Formatting = Formatting.Indented, // 格式化输出JSON NullValueHandling = NullValueHandling.Ignore, // 忽略空值属性 // 移除了错误的 Encoding = Encoding.UTF8 配置 StringEscapeHandling = StringEscapeHandling.EscapeNonAscii // 可选:转义非ASCII字符(如中文) }; return JsonConvert.SerializeObject(obj, settings); } /// <summary> /// 反序列化方法(无错误) /// </summary> private T DeserializeFromJson<T>(string json) { try { var settings = new JsonSerializerSettings { MissingMemberHandling = MissingMemberHandling.Ignore // 忽略JSON中不存在的属性 }; return JsonConvert.DeserializeObject<T>(json, settings); } catch (JsonException ex) { Log($"JSON反序列化失败:{ex.Message}"); return default(T); } } /// <summary> /// 日志输出 /// </summary> private void Log(string message) { if (txtLog.InvokeRequired) { txtLog.Invoke(new Action<string>(Log), message); } else { txtLog.AppendText($"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] {message}{Environment.NewLine}"); txtLog.ScrollToCaret(); } } #endregion }}

APIPost软件测试:

关键代码解释
-
1、HttpListener
:核心类,用于监听 HTTP 请求,支持多前缀、多请求处理
-
2、多线程处理
:监听线程和请求处理线程分离,避免阻塞 UI 线程
-
3、JSON 序列化 / 反序列化
:使用
JavaScriptSerializer处理 JSON 数据(也可以替换为 Newtonsoft.Json,更推荐) -
4、跨线程 UI 更新
:通过
Control.Invoke实现日志的跨线程输出,避免 WinForm 跨线程访问异常 -
5、异常处理
:完善的异常捕获和错误响应,保证服务器稳定运行
总结
-
1、该 WinForm 服务器基于
HttpListener实现,能够稳定处理 JSON 格式的 GET/POST 请求,核心是异步监听 + 多线程处理请求,避免阻塞 UI。 -
2、关键要点:需要管理员权限运行、正确处理跨线程 UI 更新、严格遵循 HTTP 响应规范(设置 Content-Type、关闭响应流)。