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: https://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; }
        }

<pre><code>    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;
}
/// &lt;summary&gt;
/// Description of NANWebserver.
/// &lt;/summary&gt;
[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");
        }

<pre><code>    void MainFormFormClosed(object sender, FormClosedEventArgs e)
    {
        this.nanWebserver1.Stop();
    }

NANWebserver Klasse Downloads: 6748 times

Related posts

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.

*