为了保持简介,我会提到我一直在构建一个应用程序,它涉及从我建立的私人网站执行远程命令,并让我的个人家用计算机响应这些命令。
我发现实时桌面流是一个完美的功能,我打算使用iframe将其融入我的网站。但是,我似乎无法找到一个好的C#库,它允许我实时流式传输我的桌面。
除此之外:http://www.codeproject.com/Articles/371955/Motion-JPEG-Streaming-Server
问题是,这只允许我将桌面流式传输到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;
}
}
}
MjpegWriter
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
}
}
答案 0 :(得分:0)
此应用程序也应该在互联网上运行。确保您通过远程访问的端口已打开。
如果您不想打开应用程序工作的端口。然后考虑改变上面的源代替反向连接,而台式计算机则充当客户端而不是服务器。
祝你好运