C# JPEG流媒体问题-如何将图像流媒体到我选择的服务器?

C# JPEG流媒体问题-如何将图像流媒体到我选择的服务器?,c#,motion,mjpeg,C#,Motion,Mjpeg,为了简短介绍,我将提到我一直在构建一个应用程序,其中包括从我构建的私人网站执行远程命令,并让我的个人家庭计算机响应这些命令 我发现实时桌面流媒体将是一个完美的功能,我计划使用iframe将其安装到我的网站中。然而,我似乎找不到一个好的C#库,它可以让我实时地流式处理我的桌面 除此之外: 问题是,这只允许我将桌面流式传输到localhost、127.0.0.1和其他本地主机链接 我需要一种方法来修改它,使它能够流到我选择的服务器,然后我可以从该服务器访问它。例如www.mystream.com/s

为了简短介绍,我将提到我一直在构建一个应用程序,其中包括从我构建的私人网站执行远程命令,并让我的个人家庭计算机响应这些命令

我发现实时桌面流媒体将是一个完美的功能,我计划使用iframe将其安装到我的网站中。然而,我似乎找不到一个好的C#库,它可以让我实时地流式处理我的桌面

除此之外:

问题是,这只允许我将桌面流式传输到localhost、127.0.0.1和其他本地主机链接

我需要一种方法来修改它,使它能够流到我选择的服务器,然后我可以从该服务器访问它。例如www.mystream.com/stream.php

它由两个类组成:ImageStreamingServer.cs

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
    }
}