C# JPEG流媒体问题-如何将图像流媒体到我选择的服务器?
为了简短介绍,我将提到我一直在构建一个应用程序,其中包括从我构建的私人网站执行远程命令,并让我的个人家庭计算机响应这些命令 我发现实时桌面流媒体将是一个完美的功能,我计划使用iframe将其安装到我的网站中。然而,我似乎找不到一个好的C#库,它可以让我实时地流式处理我的桌面 除此之外: 问题是,这只允许我将桌面流式传输到localhost、127.0.0.1和其他本地主机链接 我需要一种方法来修改它,使它能够流到我选择的服务器,然后我可以从该服务器访问它。例如www.mystream.com/stream.php 它由两个类组成:ImageStreamingServer.csC# JPEG流媒体问题-如何将图像流媒体到我选择的服务器?,c#,motion,mjpeg,C#,Motion,Mjpeg,为了简短介绍,我将提到我一直在构建一个应用程序,其中包括从我构建的私人网站执行远程命令,并让我的个人家庭计算机响应这些命令 我发现实时桌面流媒体将是一个完美的功能,我计划使用iframe将其安装到我的网站中。然而,我似乎找不到一个好的C#库,它可以让我实时地流式处理我的桌面 除此之外: 问题是,这只允许我将桌面流式传输到localhost、127.0.0.1和其他本地主机链接 我需要一种方法来修改它,使它能够流到我选择的服务器,然后我可以从该服务器访问它。例如www.mystream.com/s
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Windows.Forms;
using System.IO;
// -------------------------------------------------
// Developed By : Ragheed Al-Tayeb
// e-Mail : ragheedemail@gmail.com
// Date : April 2012
// -------------------------------------------------
namespace rtaNetworking.Streaming
{
/// <summary>
/// Provides a streaming server that can be used to stream any images source
/// to any client.
/// </summary>
public class ImageStreamingServer:IDisposable
{
private List<Socket> _Clients;
private Thread _Thread;
public ImageStreamingServer():this(Screen.Snapshots(600,450,true))
{
}
public ImageStreamingServer(IEnumerable<Image> imagesSource)
{
_Clients = new List<Socket>();
_Thread = null;
this.ImagesSource = imagesSource;
this.Interval = 50;
}
/// <summary>
/// Gets or sets the source of images that will be streamed to the
/// any connected client.
/// </summary>
public IEnumerable<Image> ImagesSource { get; set; }
/// <summary>
/// Gets or sets the interval in milliseconds (or the delay time) between
/// the each image and the other of the stream (the default is .
/// </summary>
public int Interval { get; set; }
/// <summary>
/// Gets a collection of client sockets.
/// </summary>
public IEnumerable<Socket> Clients { get { return _Clients; } }
/// <summary>
/// Returns the status of the server. True means the server is currently
/// running and ready to serve any client requests.
/// </summary>
public bool IsRunning { get { return (_Thread != null && _Thread.IsAlive); } }
/// <summary>
/// Starts the server to accepts any new connections on the specified port.
/// </summary>
/// <param name="port"></param>
public void Start(int port)
{
lock (this)
{
_Thread = new Thread(new ParameterizedThreadStart(ServerThread));
_Thread.IsBackground = true;
_Thread.Start(port);
}
}
/// <summary>
/// Starts the server to accepts any new connections on the default port (8080).
/// </summary>
public void Start()
{
this.Start(8080);
}
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;
}
}
}
/// <summary>
/// This the main thread of the server that serves all the new
/// connections from clients.
/// </summary>
/// <param name="state"></param>
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(10);
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();
}
/// <summary>
/// Each client connection will be served by this thread.
/// </summary>
/// <param name="client"></param>
private void ClientThread(object client)
{
Socket socket = (Socket)client;
System.Diagnostics.Debug.WriteLine(string.Format("New client from {0}",socket.RemoteEndPoint.ToString()));
lock (_Clients)
_Clients.Add(socket);
try
{
using (MjpegWriter wr = new MjpegWriter(new NetworkStream(socket, true)))
{
// Writes the response header to the client.
wr.WriteHeader();
// Streams the images from the source to the client.
foreach (var imgStream in Screen.Streams(this.ImagesSource))
{
if (this.Interval > 0)
Thread.Sleep(this.Interval);
wr.Write(imgStream);
}
}
}
catch { }
finally
{
lock (_Clients)
_Clients.Remove(socket);
}
}
#region IDisposable Members
public void Dispose()
{
this.Stop();
}
#endregion
}
static class SocketExtensions
{
public static IEnumerable<Socket> IncommingConnectoins(this Socket server)
{
while(true)
yield return server.Accept();
}
}
static class Screen
{
public static IEnumerable<Image> Snapshots()
{
return Screen.Snapshots(System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width, System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height,true);
}
/// <summary>
/// Returns a
/// </summary>
/// <param name="delayTime"></param>
/// <returns></returns>
public static IEnumerable<Image> Snapshots(int width,int height,bool showCursor)
{
Size size = new Size(System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width, System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height);
Bitmap srcImage = new Bitmap(size.Width, size.Height);
Graphics srcGraphics = Graphics.FromImage(srcImage);
bool scaled = (width != size.Width || height != size.Height);
Bitmap dstImage = srcImage;
Graphics dstGraphics = srcGraphics;
if(scaled)
{
dstImage = new Bitmap(width, height);
dstGraphics = Graphics.FromImage(dstImage);
}
Rectangle src = new Rectangle(0, 0, size.Width, size.Height);
Rectangle dst = new Rectangle(0, 0, width, height);
Size curSize = new Size(32, 32);
while (true)
{
srcGraphics.CopyFromScreen(0, 0, 0, 0, size);
if (showCursor)
Cursors.Default.Draw(srcGraphics,new Rectangle(Cursor.Position,curSize));
if (scaled)
dstGraphics.DrawImage(srcImage, dst, src, GraphicsUnit.Pixel);
yield return dstImage;
}
srcGraphics.Dispose();
dstGraphics.Dispose();
srcImage.Dispose();
dstImage.Dispose();
yield break;
}
internal static IEnumerable<MemoryStream> Streams(this IEnumerable<Image> source)
{
MemoryStream ms = new MemoryStream();
foreach (var img in source)
{
ms.SetLength(0);
img.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
yield return ms;
}
ms.Close();
ms = null;
yield break;
}
}
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
使用系统图;
Net系统;
使用System.Net.Sockets;
使用系统线程;
使用System.Windows.Forms;
使用System.IO;
// -------------------------------------------------
//开发人:拉希德·塔耶布
//电邮:ragheedemail@gmail.com
//日期:2012年4月
// -------------------------------------------------
名称空间网络。流
{
///
///提供可用于流式处理任何图像源的流式处理服务器
///给任何客户。
///
公共类ImageStreamingServer:IDisposable
{
私人名单客户;
私有线程(u线程),;
publicmagestreamingserver():这个(Screen.Snapshots(600450,true))
{
}
公共ImageStreamingServer(IEnumerable imagesSource)
{
_Clients=新列表();
_线程=null;
this.ImagesSource=ImagesSource;
这个时间间隔=50;
}
///
///获取或设置将流式传输到的图像的源
///任何连接的客户端。
///
公共IEnumerable ImagesSource{get;set;}
///
///获取或设置之间的间隔(毫秒或延迟时间)
///流中的每个图像和另一个图像(默认值为。
///
公共整数间隔{get;set;}
///
///获取客户端套接字的集合。
///
公共IEnumerable客户端{get{return\u Clients;}}
///
///返回服务器的状态。True表示服务器当前处于
///正在运行并准备好为任何客户端请求提供服务。
///
公共bool正在运行{get{return(_-Thread!=null&&&u-Thread.IsAlive);}
///
///启动服务器以接受指定端口上的任何新连接。
///
///
公共无效开始(int端口)
{
锁(这个)
{
_线程=新线程(新的参数化线程启动(服务器线程));
_Thread.IsBackground=true;
_线程启动(端口);
}
}
///
///启动服务器以接受默认端口(8080)上的任何新连接。
///
公开作废开始()
{
这个。启动(8080);
}
公共停车场()
{
如果(此.IsRunning)
{
尝试
{
_Thread.Join();
_Thread.Abort();
}
最后
{
锁定(_客户端)
{
foreach(客户中的var s)
{
尝试
{
s、 Close();
}
捕获{}
}
_Clients.Clear();
}
_线程=null;
}
}
}
///
///这是服务器的主线程,为所有新的
///来自客户端的连接。
///
///
私有void服务器线程(对象状态)
{
尝试
{
套接字服务器=新套接字(AddressFamily.InterNetwork、SocketType.Stream、ProtocolType.Tcp);
Bind(新的IPEndPoint(IPAddress.Any,(int)状态));
听(10);
System.Diagnostics.Debug.WriteLine(string.Format(“服务器在端口{0}上启动,状态));
foreach(服务器中的套接字客户端。IncommingConnectoins())
QueueUserWorkItem(新的WaitCallback(ClientThread),客户端);
}
捕获{}
这个。停止();
}
///
///每个客户端连接都将由该线程提供服务。
///
///
私有void客户端线程(对象客户端)
{
套接字=(套接字)客户端;
System.Diagnostics.Debug.WriteLine(string.Format(“来自{0}的新客户端”,socket.RemoteEndPoint.ToString());
锁定(_客户端)
_Clients.Add(socket);
尝试
{
使用(MjpegWriter wr=newmjpegwriter(newnetworkstream(socket,true)))
{
//将响应头写入客户端。
wr.WriteHeader();
//将图像从源流传输到客户端。
foreach(Screen.Streams中的var imgStream(this.ImagesSource))
{
如果(此间隔>0)
线程睡眠(这个间隔);
wr.Write(imgStream);
}
}
}
捕获{}
最后
{
锁定(_客户端)
_客户
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Drawing;
// -------------------------------------------------
// Developed By : Ragheed Al-Tayeb
// e-Mail : ragheedemail@gmail.com
// Date : April 2012
// -------------------------------------------------
namespace rtaNetworking.Streaming
{
/// <summary>
/// Provides a stream writer that can be used to write images as MJPEG
/// or (Motion JPEG) to any stream.
/// </summary>
public class MjpegWriter:IDisposable
{
private static byte[] CRLF = new byte[] { 13, 10 };
private static byte[] EmptyLine = new byte[] { 13, 10, 13, 10};
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, 0, data.Length);
}
private void Write(string text)
{
byte[] data = BytesOf(text);
this.Stream.Write(data, 0, 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,0,data.Length);
if (count != 0)
return Encoding.ASCII.GetString(data, 0, count);
return null;
}
#region IDisposable Members
public void Dispose()
{
try
{
if (this.Stream != null)
this.Stream.Dispose();
}
finally
{
this.Stream = null;
}
}
#endregion
}
}