实现流写入,将图像作为mjpeg写入

 public class MjpegWriter : IDisposable
{ private static byte[] CRLF = new byte[] { , };
private static byte[] EmptyLine = new byte[] { , , , }; private string _Boundary; public MjpegWriter(Stream stream)
: this(stream, "--boundary")
{ } public MjpegWriter(Stream stream, string boundary)
{ this.Stream = stream;
this.Boundary = boundary;
} public string Boundary { get; private set; }
public Stream Stream { get; private set; } public void WriteHeader()
{ Write(
"HTTP/1.1 200 OK\r\n" +
"Content-Type: multipart/x-mixed-replace; boundary=" +
this.Boundary +
"\r\n"
); this.Stream.Flush();
} public void Write(Image image)
{
MemoryStream ms = BytesOf(image);
this.Write(ms);
} public void Write(MemoryStream imageStream)
{ StringBuilder sb = new StringBuilder(); sb.AppendLine();
sb.AppendLine(this.Boundary);
sb.AppendLine("Content-Type: image/jpeg");
sb.AppendLine("Content-Length: " + imageStream.Length.ToString());
sb.AppendLine(); Write(sb.ToString());
imageStream.WriteTo(this.Stream);
Write("\r\n"); this.Stream.Flush(); } private void Write(byte[] data)
{
this.Stream.Write(data, , data.Length);
} private void Write(string text)
{
byte[] data = BytesOf(text);
this.Stream.Write(data, , data.Length);
} private static byte[] BytesOf(string text)
{
return Encoding.ASCII.GetBytes(text);
} private static MemoryStream BytesOf(Image image)
{
MemoryStream ms = new MemoryStream();
image.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
return ms;
} public string ReadRequest(int length)
{ byte[] data = new byte[length];
int count = this.Stream.Read(data, , data.Length); if (count != )
return Encoding.ASCII.GetString(data, , count); return null;
} #region IDisposable Members public void Dispose()
{ try
{ if (this.Stream != null)
this.Stream.Dispose(); }
finally
{
this.Stream = null;
}
} #endregion
}

服务器实现:

 public class ImageStreamingServer : IDisposable
{ private List<Socket> _Clients;
private Thread _Thread; public ImageStreamingServer() : this(IRImg.Snapshots())
{ } public ImageStreamingServer(IEnumerable<Image> imagesSource)
{ _Clients = new List<Socket>();
_Thread = null; this.ImagesSource = imagesSource;
this.Interval = ; } public IEnumerable<Image> ImagesSource { get; set; } public int Interval { get; set; } public IEnumerable<Socket> Clients { get { return _Clients; } } public bool IsRunning { get { return (_Thread != null && _Thread.IsAlive); } } public void Start(int port)
{ lock (this)
{
_Thread = new Thread(new ParameterizedThreadStart(ServerThread));
_Thread.IsBackground = true;
_Thread.Start(port);
} } public void Start()
{
this.Start();
} public void Stop()
{ if (this.IsRunning)
{
try
{
_Thread.Join();
_Thread.Abort();
}
finally
{ lock (_Clients)
{ foreach (var s in _Clients)
{
try
{
s.Close();
}
catch { }
}
_Clients.Clear(); } _Thread = null;
}
}
} private void ServerThread(object state)
{ try
{
Socket Server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); Server.Bind(new IPEndPoint(IPAddress.Any, (int)state));
Server.Listen(); System.Diagnostics.Debug.WriteLine(string.Format("Server started on port {0}.", state)); foreach (Socket client in Server.IncommingConnectoins())
ThreadPool.QueueUserWorkItem(new WaitCallback(ClientThread), client); }
catch { } this.Stop();
} private void ClientThread(object client)
{ Socket socket = (Socket)client;
lock (_Clients)
_Clients.Add(socket); try
{
using (MjpegWriter wr = new MjpegWriter(new NetworkStream(socket, true)))
{
wr.WriteHeader();
foreach (var imgStream in IRImg.Streams(this.ImagesSource))
{
if (this.Interval > )
Thread.Sleep(this.Interval); wr.Write(imgStream);
} }
}
catch { }
finally
{
lock (_Clients)
_Clients.Remove(socket);
}
} public void Dispose()
{
this.Stop();
}
} static class SocketExtensions
{ public static IEnumerable<Socket> IncommingConnectoins(this Socket server)
{
while (true)
yield return server.Accept();
} } static class IRImg
{
public static IEnumerable<Image> Snapshots()
{
while (true)
{
yield return IRCommon.Instance.GetBitmap();
}
} internal static IEnumerable<MemoryStream> Streams(this IEnumerable<Image> source)
{
MemoryStream ms = new MemoryStream(); foreach (var img in source)
{
ms.SetLength();
img.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
yield return ms;
} ms.Close();
ms = null; yield break;
} }

将上面代码中的这行 IRCommon.Instance.GetBitmap();改为自己的bitmap来源即可实现mjpeg图像传输

浏览器可直接输入 127.0.0.1:8080访问,chrome没问题,但是ie下,会一直下载图片

C#客户端可以用afroge实现浏览,具体可参考:在WPF中使用AForge控件

本项目来源:Motion JPEG Streaming Server   (codeproject)

C#实现MJPEG服务器的更多相关文章

  1. 适用于Windows和Linux的Yolo-v3和Yolo-v2(上)

    适用于Windows和Linux的Yolo-v3和Yolo-v2(上) https://github.com/eric-erki/darknetAB (用于对象检测的神经网络)-Tensor Core ...

  2. C#开源实现MJPEG流传输

    本文为 Dennis Gao 原创技术文章,发表于博客园博客,未经作者本人允许禁止任何形式的转载. 许久以前写了篇文章<基于.NET打造IP智能网络视频监控系统>,记录和介绍了自己几年来积 ...

  3. Web服务器部署浅析

    企业内网站 中小型企业一般将企业宣传网站外包给第三方进行统一设计.部署和运维.大型企业因为访问量和数据量有所增加,部分网站可能具备在线咨询或订单的功能,此类Web服务器采用最通用的IU机架式服务器以降 ...

  4. 基于mjpg_streamer视频服务器移植【转】

    本文转载自:http://blog.csdn.net/wavemcu/article/details/7539560 MJPG简介: MJPG是MJPEG的缩写,但是MJPEG还可以表示文件格式扩展名 ...

  5. M-JPEG和MPEG-4的区别 M-JPEG VS MPEG

    http://blog.sina.com.cn/s/blog_4b357b300100gre9.html M-JPEG VS MPEG http://blog.csdn.net/bluesky_sun ...

  6. 网络摄像头Androi端显示(mjpeg)源码分析

    main.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:and ...

  7. M-JPEG、MPEG4、H.264都有何区别

    压缩方式是网络视频服务器和网络摄像机的核心技术,压缩方式很大程度上决定着图像的质量.压缩比.传输效率.传输速度等性能,它是评价网络视频服务器和网络摄像机性能优劣的重要一环.随着多媒体技术的发展,相继推 ...

  8. arm开发板6410/2440上mjpg-streamer网络视频服务器移植

    摄像头移植 一.环境 主机环境 :ubuntu 10.10         目标板 :FS-S5PC100 主机工具链 :gcc-4.4.5         交叉工具链 :arm-unknown-li ...

  9. 基于mjpg-streamer网络视频服务器移植

    MJPG简介: MJPG是MJPEG的缩写,但是MJPEG还可以表示文件格式扩展名. MJPEG 全名为 "Motion Joint Photographic Experts Group&q ...

随机推荐

  1. sql server 防 注入

    这里使用的是参数化 SqlParameter useremail = new SqlParameter("@useremail", user.user_Email); SqlPar ...

  2. windows BAT脚本2个服务器间传递文件

    1. 脚本功能: 实现2个服务器间文件的传递,例如从A服务器往B服务器上传文件 2. 实现步骤: 2.1 服务器连结,找到指定路径,读取所需要上传的文件,将文件名称复制到一个文件下 (此处考虑可能需要 ...

  3. Python怎么检验数据的正态分布

    在对数据建模前,很多时候我们需要对数据做正态性检验,进而通过检验结果确定下一步的分析方案.下面介绍 Python 中常用的几种正态性检验方法: scipy.stats.kstest kstest 是一 ...

  4. Android基础相关面试问题-activity面试问题(生命周期,任务栈,启动模式,跳转协议,启动流程)

    关于Android的一些面试题在15年就已经开了这个专栏了,但是一直木有坚持收集,而每次面对想要跳槽时大脑一片空白,也有些恐惧,因为毕境面试都是纯技术的沟通,要想让公司对你的技术能有所认可会全方位的进 ...

  5. Event Binding in Angular

    https://www.pluralsight.com/guides/angular-event-binding Introduction In this guide, we will explore ...

  6. np中的随机函数

      numpy.random.uniform介绍: 1. 函数原型:  numpy.random.uniform(low,high,size)  ==>也即其他函数是对该函数的进一步封装 功能: ...

  7. Bootstrap-轮播图-No.3

    <!DOCTYPE html> <html lang="zh"> <head> <meta charset="UTF-8&quo ...

  8. ACM-ICPC 2017 西安赛区现场赛 K. LOVER II && LibreOJ#6062. 「2017 山东一轮集训 Day2」Pair(线段树)

    题目链接:西安:https://nanti.jisuanke.com/t/20759   (计蒜客的数据应该有误,题目和 LOJ 的大同小异,题解以 LOJ 为准)     LOJ:https://l ...

  9. BZOJ 1982 / Luogu SP2021: [Spoj 2021]Moving Pebbles (找平衡状态)

    这道题在论文里看到过,直接放论文原文吧 在BZOJ上是单组数据,而且数据范围符合,直接int读入排序就行了.代码: #include <cstdio> #include <algor ...

  10. springboot注释层分解图