C#开源实现MJPEG流传输
C#开源实现MJPEG流传输为什么需要MJPEG流传输在物联网、安防监控和远程桌面场景中MJPEGMotion JPEG是一种简单而实用的视频流格式。它将每一帧JPEG图片连续传输无需复杂的编码器兼容性极强——任何支持img标签的浏览器都能直接播放。相比H.264或VP9MJPEG实现成本低、延迟小非常适合教学或轻量级应用。本文将带你从零搭建一个C# MJPEG流服务器并逐步优化到生产级用法。### 基础概念HTTP响应与多部分内容MJPEG的核心是HTTP的multipart/x-mixed-replace响应。服务器不断向客户端发送JPEG帧每个帧以--boundary分隔。客户端如浏览器收到后自动刷新显示最新帧。我们先用最简代码实现单帧传输。#### 代码示例1最小化MJPEG服务器控制台应用csharpusing System;using System.Net;using System.Net.Sockets;using System.Text;using System.Threading;class MinimalMjpegServer{ static void Main() { TcpListener listener new TcpListener(IPAddress.Any, 8080); listener.Start(); Console.WriteLine(MJPEG服务器启动访问 http://localhost:8080); while (true) { TcpClient client listener.AcceptTcpClient(); ThreadPool.QueueUserWorkItem(HandleClient, client); } } static void HandleClient(object state) { var client (TcpClient)state; var stream client.GetStream(); // 1. 读取HTTP请求头简化版 byte[] buffer new byte[1024]; stream.Read(buffer, 0, buffer.Length); string request Encoding.ASCII.GetString(buffer); Console.WriteLine(收到请求: request.Split(\n)[0]); // 2. 发送HTTP响应头声明MJPEG流 string header HTTP/1.1 200 OK\r\n Content-Type: multipart/x-mixed-replace; boundaryframe\r\n Connection: close\r\n\r\n; byte[] headerBytes Encoding.ASCII.GetBytes(header); stream.Write(headerBytes, 0, headerBytes.Length); // 3. 用一张简易生成的JPEG图这里用1x1像素红色图 byte[] jpegData CreateRedJpeg(); // 4. 持续发送帧这里只发5帧演示 for (int i 0; i 5; i) { string boundary --frame\r\n Content-Type: image/jpeg\r\n Content-Length: jpegData.Length \r\n\r\n; byte[] boundaryBytes Encoding.ASCII.GetBytes(boundary); stream.Write(boundaryBytes, 0, boundaryBytes.Length); stream.Write(jpegData, 0, jpegData.Length); stream.Write(Encoding.ASCII.GetBytes(\r\n), 0, 2); Thread.Sleep(1000); // 每秒一帧 } client.Close(); } static byte[] CreateRedJpeg() { // 使用System.Drawing生成1x1红色JPEG需引用System.Drawing.Common using (var bmp new System.Drawing.Bitmap(1, 1)) { bmp.SetPixel(0, 0, System.Drawing.Color.Red); using (var ms new System.IO.MemoryStream()) { bmp.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg); return ms.ToArray(); } } }}运行效果浏览器访问后显示红色画面5秒。但此代码有严重缺陷不处理并发、不解析真实请求、不区分GET/POST。现在我们来升级。### 进阶实现完整异步服务器与摄像头采集生产级MJPEG需要处理多客户端、异步I/O、以及从摄像头抓帧。我们将使用HttpListener简化HTTP解析并引入OpenCV或Windows摄像头API获取实时画面。这里用模拟数据演示帧生成。#### 代码示例2异步MJPEG流服务器支持多客户端csharpusing System;using System.Net;using System.Text;using System.Threading.Tasks;using System.Drawing;using System.Drawing.Imaging;using System.IO;using System.Collections.Concurrent;class AdvancedMjpegServer{ // 用并发字典管理客户端输出流 static ConcurrentDictionaryStream, byte _clients new ConcurrentDictionaryStream, byte(); static async Task Main() { HttpListener listener new HttpListener(); listener.Prefixes.Add(http://:8080/); listener.Start(); Console.WriteLine(高级MJPEG服务器启动 http://localhost:8080/stream); // 启动后台帧广播任务 var broadcastTask Task.Run(BroadcastFrames); while (true) { var context await listener.GetContextAsync(); _ HandleRequest(context); // 异步处理不阻塞 } } static async Task HandleRequest(HttpListenerContext context) { if (context.Request.Url.AbsolutePath /stream) { // 设置MJPEG响应头 context.Response.ContentType multipart/x-mixed-replace; boundaryframe; context.Response.StatusCode 200; context.Response.AddHeader(Cache-Control, no-cache); var stream context.Response.OutputStream; _clients.TryAdd(stream, 0); // 保持连接直到客户端断开 while (true) { try { await Task.Delay(Timeout.Infinite); } catch (Exception) { _clients.TryRemove(stream, out _); stream.Close(); break; } } } else { context.Response.StatusCode 404; context.Response.Close(); } } static async Task BroadcastFrames() { int frameIndex 0; while (true) { // 生成模拟帧这里用时间戳动态生成JPEG byte[] jpeg GenerateFrame(frameIndex); foreach (var client in _clients.Keys) { try { string boundary --frame\r\nContent-Type: image/jpeg\r\nContent-Length: jpeg.Length \r\n\r\n; byte[] header Encoding.ASCII.GetBytes(boundary); await client.WriteAsync(header, 0, header.Length); await client.WriteAsync(jpeg, 0, jpeg.Length); await client.WriteAsync(Encoding.ASCII.GetBytes(\r\n), 0, 2); await client.FlushAsync(); } catch (Exception) { // 客户端断开移除 _clients.TryRemove(client, out _); } } await Task.Delay(100); // 10FPS } } static byte[] GenerateFrame(int index) { // 创建带文字的动态图片模拟摄像头画面 using (var bmp new Bitmap(320, 240)) { using (var g Graphics.FromImage(bmp)) { g.Clear(Color.DarkBlue); g.DrawString($Frame {index}, new Font(Arial, 20), Brushes.White, 50, 100); } using (var ms new MemoryStream()) { bmp.Save(ms, ImageFormat.Jpeg); return ms.ToArray(); } } }}关键改进- 使用HttpListener自动解析HTTP请求支持GET、路径匹配。- 异步I/Oasync/await不阻塞线程支持上千并发。- 后台任务统一广播帧所有客户端共享同一帧源节省CPU。### 生产级优化与开源生态#### 1. 性能瓶颈与解决方案-帧生成效率使用System.Drawing生成JPEG较慢建议改用ImageSharp跨平台或OpenCvSharp硬件加速。-网络拥塞为每个客户端添加缓冲队列慢客户端不应拖累整体。-帧率控制通过Stopwatch精确控制FPS避免Task.Delay误差。#### 2. 开源库推荐-MJPEG-Streamer.NET基于.NET 6的完整实现支持RTSP转MJPEG。-Camera.MAUI跨平台摄像头采集可直接输出MJPEG帧。-AForge.NET老牌视频处理库含MJPEG写入器。#### 3. 安全与认证- 添加Basic Auth检查Authorization头。- 限制IP白名单。- 使用HTTPS配置证书防止帧数据被窃听。### 完整代码整合从摄像头到Web这里提供一个可运行的真实案例使用OpenCvSharp调用USB摄像头通过异步服务器广播。由于篇幅仅展示核心片段csharp// 安装NuGet包: OpenCvSharp4, OpenCvSharp4.runtime.winusing OpenCvSharp;class CameraBroadcaster{ VideoCapture _capture; public CameraBroadcaster() { _capture new VideoCapture(0); // 打开第一个摄像头 _capture.FrameWidth 640; _capture.FrameHeight 480; } public byte[] GetFrame() { using (var frame new Mat()) { _capture.Read(frame); if (frame.Empty()) return null; // Mat转JPEG字节 Cv2.ImEncode(.jpg, frame, out byte[] jpeg); return jpeg; } }}然后在BroadcastFrames中调用GetFrame()即可。### 总结本文从HTTP协议基础出发用两个递进示例展示了C#实现MJPEG流传输的全过程先理解multipart/x-mixed-replace原理再构建异步并发服务器最后结合开源库扩展真实应用。MJPEG虽不如现代编码器高效但其简单性使其在嵌入式、教学和低延迟场景中仍有价值。建议读者进一步研究如何结合System.Threading.Channels实现背压控制或使用INotifyPropertyChanged整合到WPF界面。掌握这一技术你将能快速搭建自己的视频监控系统。

相关新闻

C++实现拖拉机纸牌游戏:面向对象设计与复杂规则算法实践

C++实现拖拉机纸牌游戏:面向对象设计与复杂规则算法实践

1. 项目概述与核心思路 最近在整理一些老项目,翻出来一个几年前用C写的拖拉机纸牌游戏。当时写这个,一方面是觉得市面上的纸牌游戏要么太简单,要么规则不地道,想自己实现一个规则严谨、体验流畅的版本;另一方面&#x…

2026/10/4 17:54:44 阅读更多 →
Python实现Excel工作表批量转图片的高效方案

Python实现Excel工作表批量转图片的高效方案

1. 项目概述:Excel工作表批量转图片工具 这个工具的核心功能是将Excel工作簿中的多个工作表批量转换为图片格式。不同于简单的截图操作,它能自动识别工作簿中的所有工作表,并按需生成高质量图片文件。对于需要将报表、数据分析结果或财务表格…

2026/10/6 8:45:32 阅读更多 →
OpenBMC硬件资产管理:Inventory系统架构与应用实践

OpenBMC硬件资产管理:Inventory系统架构与应用实践

1. OpenBMC与硬件资产管理的关系 OpenBMC作为开源基板管理控制器(Baseboard Management Controller)的实现方案,在现代数据中心和服务器管理中扮演着关键角色。它通过统一的接口提供对服务器硬件的监控和管理能力,而硬件资产信息的…

2026/9/30 16:56:07 阅读更多 →

最新新闻

Sentinel-LDK-Run-time-setup8.15:运行时环境搭建与避坑指南

Sentinel-LDK-Run-time-setup8.15:运行时环境搭建与避坑指南

简介:Sentinel-LDK-Run-time-setup8.15 是一份面向软件授权与加密保护开发者的运行时环境安装资源,主要服务于需要部署 Sentinel LDK 加密狗运行环境的工程师与技术支持人员,帮助解决授权组件在目标机器上无法正常识别或加载的问题。压缩包共…

2026/10/11 11:47:15 阅读更多 →
市级30m DEM数据处理全流程:从坐标系检查到坡度坡向与水文分析

市级30m DEM数据处理全流程:从坐标系检查到坡度坡向与水文分析

简介:这份资源面向地理信息科学、城市规划、环境研究与灾害风险评估等领域的从业者与学习者,提供江西省赣州市30米分辨率的DEM数字高程数据,并附带本市级行政范围矢量文件,可用于地形分析、坡度坡向计算、水文与交通线路规划等场景…

2026/10/11 11:47:15 阅读更多 →
WinForms自绘TabControl:从OwnerDraw到高DPI适配的完整实现

WinForms自绘TabControl:从OwnerDraw到高DPI适配的完整实现

简介:这是一份面向C#桌面应用开发者的TabControl控件定制化学习资源,聚焦Windows Forms界面美化与交互增强,适用于希望突破默认UI限制、提升产品视觉表现力的中初级开发者。资源提供完整的美化版TabControl源码实现,涵盖自定义绘制…

2026/10/11 11:47:15 阅读更多 →
思考慢到 13.4 秒?用 MTP 投机解码把 GEV 的 System 2 提速 1.8 倍

思考慢到 13.4 秒?用 MTP 投机解码把 GEV 的 System 2 提速 1.8 倍

思考慢到 13.4 秒?用 MTP 投机解码把 GEV 的 System 2 提速 1.8 倍 【免费下载链接】GEV-26B-Decide 项目地址: https://ai.gitcode.com/hf_mirrors/autotrust/GEV-26B-Decide 当一个大模型「回答一个问题要等 13 秒」,你会怎么想?如…

2026/10/11 11:47:15 阅读更多 →
Pastel 下载历史版本时如何保护 Apple 账户安全?钥匙串与 AES-256-GCM 会话加密完整指南

Pastel 下载历史版本时如何保护 Apple 账户安全?钥匙串与 AES-256-GCM 会话加密完整指南

【免费下载链接】Pastel-macOS 在 Mac 上搜索并下载 iOS、iPadOS 与 visionOS App 的历史版本,管理 IPA,并通过隔空投送发送至 iPhone 或 iPad。 项目地址: https://gitcode.com/gh_mirrors/ipa/Pastel-macOS 点击查看 免费下载 &#x1f51…

2026/10/11 11:47:15 阅读更多 →
YOLOv8果蔬识别实战:数据、部署与可视化三大硬骨头

YOLOv8果蔬识别实战:数据、部署与可视化三大硬骨头

简介:本资源是一套基于YOLOv8实现的果蔬识别系统完整项目,专为计算机相关专业学生完成期末大作业、课程设计或毕业设计提供高分参考方案。项目经导师指导与助教审定,评审得分98分,源码全部本地编译通过、严格调试可直接运行&#…

2026/10/11 11:46:15 阅读更多 →

日新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/11 0:00:27 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/11 0:00:27 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/11 10:45:37 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 21:32:20 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/10 10:38:42 阅读更多 →