====== Webserver in C# ====== ===== Version 1: Mit einem HttpListener ===== In der ersten Version habe ich einen Webserver in C# mit der Klasse ''HttpListener'' realisiert. Der folgende Quelltext zeigt einen einfache Webserver, der auf Port 12345 läuft und jede Anfrage mit einem einfachen "Hallo Client" beantwortet. using System; using System.Net; using System.IO; namespace Webserver { class MainClass { public static void Main(string[] args) { HttpListener listener = new HttpListener(); Console.WriteLine("Lausche auf Port 12345"); listener.Prefixes.Add("http://*:12345/"); listener.Start(); // Aus dem Context kann der Request und der Response gewonnen werden. HttpListenerContext ctx = listener.GetContext(); // Die Antwort wird erstellt und in ein Byte-Array konvertiert. string sAntwort = "Hallo Client\n"; byte[] aBytes = System.Text.UTF8Encoding.UTF8.GetBytes(sAntwort); // Aus dem Context wird der OutputStream verwendet. Stream sOut = ctx.Response.OutputStream; // Die Antwort wird über den Outputstream an den Client geschickt. sOut.Write(aBytes, 0, aBytes.Length); sOut.Close(); } } } ===== Version 2: Mit Netzwerksockets ===== Die zweite Version nutzt Netzwerksockets und ist bei der Implementierung näher an der Netzwerkschicht. Es könnten also leicht auch andere Netzwerkdienste außer HTTP damit realisiert werden. Ich habe bewusst nur auf der Netzwerkebene gearbeitet und weitere Abstraktionsebenen sowie schon vorhandene Serverkomponenten, die es in .NET gibt, nicht verwendet. Nach dem Start des Programms, kann man mit einem Browser auf die Adresse ''http://localhost:12345'' zugreifen und auf den Unterseiten ''http://localhost:12345/ip'' die eigene IP-Adresse und unter ''http://localhost:12345/datum'' das aktuelle Datum erfahren. Der Browser läuft auf dem Port 12345, um nicht mit anderen Diensten, die auf dem Rechner bereits laufen, in Konflikt zu geraten. Das Programm verwendet die folgenden Klassen aus den [[https://msdn.microsoft.com/de-de/library/system.net%28v=vs.110%29.aspx|System.Net-]] und [[https://msdn.microsoft.com/de-de/library/system.net.sockets%28v=vs.110%29.aspx|System.Net.Sockets-Namespaces]] für die Netzwerkkommunikation: ''IPAddress, IPEndPoint, Socket.'' Wenn du es selbst ausprobieren möchtest, solltest du hier aufhören zu lesen und die [[[[schule:c-sharp_ide|Entwicklungsumgebung]] starten, um es selbst zu programmieren. Das Programm kann nun noch beliebig erweitert werden. Im Moment wird der Typ des verschickten Inhalts noch nicht berücksichtigt und nur Text verwendet. Hier könnten man natürlich auch HTML-Seiten übermitteln und z.B. eine statische HTML-Seite wie ''index.html'' ausliefern, wenn sie angefordert wird. Oder der Server führt ein Programm mit Parametern aus und sendet das Ergebnis zurück an den Browser. Ihr merkt, dass ich nicht so kreativ bin wie ihr. using System; using System.Net; using System.Net.Sockets; namespace WebServer { class MainClass { public static void Main(string[] args) { while (true) { // IP-Adresse und Port des Servers IPAddress ipAdresse = IPAddress.Parse("127.0.0.1"); IPEndPoint ipEndpunkt = new IPEndPoint(ipAdresse, 12345); Console.WriteLine("EndPoint: " + ipEndpunkt); // Socket erstellen, mit Endpoint verbinden und auf Verbindung warten Socket socketServer = new Socket(ipEndpunkt.AddressFamily, SocketType.Stream, ProtocolType.Tcp); socketServer.Bind(ipEndpunkt); socketServer.Listen(1); // Backlog = Anzahl wartender Verbindungen // Daten empfangen und in Byte-Array ablegen byte[] buffer = new byte[512]; Socket socketClient = socketServer.Accept(); Console.WriteLine( "Verbindung hergestellt mit " + socketClient.RemoteEndPoint); socketClient.Receive(buffer); // Empfangene Daten ausgeben Console.WriteLine("Empangene Daten:"); string sDaten = ""; for (int i = 0; i < buffer.Length && buffer[i] != 0; i++) { sDaten += (char)buffer [i]; } Console.WriteLine(sDaten); // Daten auswerten und Anwort erstellen string sAntwort = ""; if (sDaten.Contains("GET /ip")) { sAntwort = "Deine IP lautet " + socketClient.RemoteEndPoint; } else if(sDaten.Contains("GET /datum")) { sAntwort = "Das heutige Datum ist " + DateTime.Now; } else { sAntwort = "Was willst du machen?"; } // Antwort in Byte-Array konvertieren und senden buffer = new byte[sAntwort.Length]; for (int i = 0; i < sAntwort.Length; i++) { buffer [i] = (byte) sAntwort[i]; } socketClient.Send(buffer); // Sockets schließen socketClient.Close(); socketServer.Close(); } } } } ===== Version 3: Mit Python ===== In dem Buch //Raspberry Pi -- programmieren mit Python// von Michael Wiegand wird in Kapitel "11: Webserver" ausführlich beschrieben, wie ein Webserver in [[Python]] programmiert, ein Sensor ausgelesen und die Daten in einer [[Datenbanken|Datenbank]] gespeichert werden. Als Grundlage dient ein TCP-Server, der im folgenden Quelltext dargestellt ist. Er kann Anfragen entgegennehmen und entsprechend reagieren. import socket import threading bind_ip = "127.0.0.1" bind_port = 8081 server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server.bind((bind_ip,bind_port)) server.listen(5) print("[*] Listening on", bind_ip, ":", bind_port) # Methode, die Anfragen von Clients behandelt def handle_client(client_socket): # Anfrage des Client ausgeben request = client_socket.recv(1024) print("[*] Received:", request) # Einen String zurücksenden client_socket.send(bytes("OK!", "utf8")) client_socket.close() while True: client,addr = server.accept() print("[*] Accepted connection from:", addr[0], ":", addr[1]) handle_client(client) # Optional: Anfrage in einem separaten Thread behandeln # client_handler = threading.Thread(target=handle_client,args=(client,)) # client_handler.start()