Holger Schadeck

Holgers gesammelte (Programmier-) Erfahrungen

Dynamischer Auto Port HTTP Webserver unter C#

Dass man in .NET C# auch multithreaded HTTP Webserver schreiben kann, dürfte jedem klar sein.

Hier mal ein Klassenbeispiel, das automatisch einen freien Port ermittelt und den NAN_Webserver als Instant Webserver startet.
Wahlweise können PHP, Perl, etc als CGI-ausführende Programme deaklariert werden samt Dateitypen, sowie das Home-Verzeiichnis, und zwar alles direkt aus dem GUI-Designer heraus.

/*
 * Erstellt mit SharpDevelop.
 * Author: Holger Schadeck 
 * Web: http://www.schadeck.eu
 */
 
using System;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Net;
using System.Net.Sockets;
using System.Windows.Forms;
using System.Windows.Forms.Design;
using System.Diagnostics;
using System.Threading;
using System.Collections;
using System.IO;
 
 
namespace libHSchadeck
{
	public class MimeTypeMap {
		public string Extension {
			get { return extension; }
			set { extension = value; }
		}
		
		public string MimeType {
			get { return mimeType; }
			set { mimeType = value; }
		}
		
		public bool IsBinary {
			get { return isBinary; }
			set { isBinary = value; }
		}
		private string extension;
		private string mimeType;
		private bool isBinary;
	}
	public class CgiExtension {
		public string Extension {
			get { return extension; }
			set { extension = value; }
		}
		
		public string ServerSubExecPath {
			get { return serverSubExecPath; }
			set { serverSubExecPath = value; }
		}
		private string extension;
		private string serverSubExecPath;
	}
	/// <summary>
	/// Description of NANWebserver.
	/// </summary>
	[SerializableAttribute]
	[Designer("System.Windows.Forms.Design.ParentControlDesigner, System.Design", typeof(IDesigner))]
	public class NANWebserver : System.Windows.Forms.UserControl
	{
		private TcpListener listener;
		private IPAddress listenAddress = IPAddress.Parse("127.0.0.1");
		private int listenPortBase = 80;
		private int listenPort = 80;
		private string pathServer = "server";
		private string pathServerSubHome = "web";
		private string[] clientIps = new string[1];
		private string[] listenHosts = new string[2];
		private CgiExtension[] cgiExtensions = new CgiExtension[0];
		private Hashtable mimeMaps = new Hashtable();
		private Process serverProcess;
		private bool closeNow = false;
		public CgiExtension[] CgiExtensions {
			get { return cgiExtensions; }
			set { cgiExtensions = value; }
		}
		public int ListenPortBase {
			get { return listenPortBase; }
			set { listenPortBase = value; }
		}
		public string PathServer {
			get { return pathServer; }
			set { pathServer = value; }
		}
		
		public string PathServerSubHome {
			get { return pathServerSubHome; }
			set { pathServerSubHome = value; }
		}
		public string[] ClientIps {
			get { return clientIps; }
			set { clientIps = value; }
		}
		public string[] ListenHosts {
			get { return listenHosts; }
			set { listenHosts = value; }
		}
		
		public NANWebserver()
		{
			this.init();
			
		}
		private void init() {
			this.clientIps[0] = "all";
			this.listenHosts[0] = "127.0.0.1";
			this.listenHosts[1] = "localhost";
			this.addMimeTable("ai:1:application/postscript;aif:1:audio/x-aiff;aiff:1:audio/x-aiff;asc:0:text/plain;au:1:audio/basic;avi:1:video/x-msvideo;bin:1:application/octet-stream;bmp:1:image/bmp;css:1:text/css;doc:1:application/msword;dtd:0:application/xml-dtd;eps:1:application/postscript;exe:1:application/octet-stream;gif:1:image/gif;htm:0:text/html;html:0:text/html;jpe:1:image/jpeg;jpeg:1:image/jpeg;jpg:1:image/jpeg;js:0:application/x-javascript;mid:1:audio/midi;midi:1:audio/midi;mov:1:video/quicktime;mp2:1:audio/mpeg;mp3:1:audio/mpeg;mpe:1:video/mpeg;mpeg:1:video/mpeg;mpg:1:video/mpeg;mpga:1:audio/mpeg;pdf:1:application/pdf;png:1:image/png;ppt:1:application/vnd:ms-powerpoint;ps:1:application/postscript;qt:1:video/quicktime;ra:1:audio/x-realaudio;ram:1:audio/x-pn-realaudio;rm:1:audio/x-pn-realaudio;rpm:1:audio/x-pn-realaudio-plugin;snd:1:audio/basic;svg:1:image/svg:xml;swf:1:application/x-shockwave-flash;tif:1:image/tiff;tiff:1:image/tiff;txt:0:text/plain;wav:1:audio/x-wav;wml:0:text/vnd:wap:wml;xls:1:application/vnd:ms-excel;xml:0:application/xml;xsl:0:application/xml;xslt:0:application/xslt:xml;xul:1:application/vnd:mozilla:xul:xml;zip:1:application/zip");
		}
		public void addMimeTable(string table) {
			foreach(string line in table.Split(';')) {
				string[] cols = line.Trim().Split(':');
				this.addMimeType(cols[0],cols[2],((cols[1] == "1") ? true : false));
			}
		}
		public bool removeMimeType(string extension) {
			if(this.existMimeType(extension)) {
				this.mimeMaps.Remove(extension);
				return true;
			} else {
				return false;
			}
		}
		public bool existMimeType(string extension) {
			return this.mimeMaps.ContainsKey(extension);
		}
		public void addMimeType(string extension, string mimeType, bool binary) {
			if(this.existMimeType(extension)) {
				this.removeMimeType(extension);
			}
			MimeTypeMap map = new MimeTypeMap();
			map.Extension = extension;
			map.MimeType = mimeType;
			map.IsBinary = binary;
			this.mimeMaps.Add(extension, map);
		}
		private void writeTypes() {
			string file = this.pathServer+"\\types.txt";
			if(File.Exists(file)) {
				File.Delete(file);
			}
			string content = "";
			foreach(MimeTypeMap map in this.mimeMaps.Values) {
				content += map.Extension+"\t"+((map.IsBinary == true) ? "1" : "0") + "\t" + map.MimeType+Environment.NewLine;
			}
			File.WriteAllText(file, content);
		}
		private void writeSettings() {
			string file = this.pathServer+"\\settings.txt";
			if(File.Exists(file)) {
				File.Delete(file);
			}
			string content = "";
			content += "port="+this.listenPort+Environment.NewLine;
			content += "docroot="+this.pathServerSubHome+Environment.NewLine;
			foreach(string host in this.listenHosts) {
				content += "hostname="+host+Environment.NewLine;
			}
			foreach(string client in this.clientIps) {
				content += "clientip="+client+Environment.NewLine;
			}
			foreach(CgiExtension ext in this.cgiExtensions) {
				content += ext.Extension+"="+ext.ServerSubExecPath+Environment.NewLine;
			}
			File.WriteAllText(file, content);
		}
		public int Start() {
			int port = this.tryStart(this.listenPortBase);
			this.listenPort = port;
			if(!this.pathServer.Contains(":")) {
				this.pathServer = Environment.CurrentDirectory+"\\"+this.pathServer;
			}
			this.writeTypes();
			this.writeSettings();
			this.startServer();
			return port;
		}
		public void Stop() {
			this.closeNow = true;
			try {
				this.serverProcess.Kill();
			} catch(Exception e) {
				Trace.WriteLine(e.Message);
			}
			try {
				string file = this.pathServer+"\\settings.txt";
			    File.Delete(file);
			} catch {
				
			}
			try {
				string file = this.pathServer+"\\types.txt";
			    File.Delete(file);
			} catch {
				
			}
			
		}
		
		private void startServer() {
			if(!this.closeNow) {
				this.serverProcess = new Process();
				this.initServer();
				this.serverProcess.Start();
			}
		}
		
		private void initServer() {
			string server = this.pathServer + "\\nanweb.exe";
			this.serverProcess.StartInfo.WorkingDirectory = this.pathServer;
			this.serverProcess.StartInfo.FileName = server;
			this.serverProcess.StartInfo.Arguments = "-s -m -bc=0";
			this.serverProcess.StartInfo.CreateNoWindow = true;
			this.serverProcess.EnableRaisingEvents = true;
			this.serverProcess.StartInfo.WindowStyle= ProcessWindowStyle.Hidden;
			this.serverProcess.StartInfo.UseShellExecute = false;
			this.serverProcess.Disposed+= delegate(object sender, EventArgs e) {
				if(!this.closeNow) {
					this.startServer();
				}
			};
			this.serverProcess.Exited+= delegate(object sender, EventArgs e) {
				if(!this.closeNow) {
					this.startServer();
				}
			};
			
		}
		private int tryStart(int port) {
			try {
				this.listener = new TcpListener(this.listenAddress, port) ;
				listener.Start();
				listener.Stop();
				return port;
			} catch {
				return this.tryStart(port+1);
			}
		}
		
	}
}

Nach Zuweisung der Werte im GUI-Editor beispielsweise folgenden Code für Formular einfügen:

void MainFormLoad(object sender, EventArgs e)
		{
			int port = this.nanWebserver1.Start();
			this.webBrowser1.Url = new Uri("http://127.0.0.1:"+port+"/index.php");
		}
		
		void MainFormFormClosed(object sender, FormClosedEventArgs e)
		{
			this.nanWebserver1.Stop();
		}

NANWebserver Klasse Downloads: 2606 times

Tags: CGI, c, code.Mime, GUI-Designer, CSHARP, Perl, port, Allgemein, webserver, dynamisch, PHP, http, server

Kommentieren

*


*