Microsoft .NET Framework SDK-Netklassen: Schreiben von vernetzten Anwendungen in verwaltetem Code

Veröffentlicht: 07. Sep 2000 | Aktualisiert: 17. Jun 2004
Von Lance Olson

Dieser Artikel skizziert das Microsoft .NET Framework SDK, ein codeverwaltetes Framework zum Erstellen von Anwendungen, die Daten über das Internet senden oder empfangen.

Auf dieser Seite

 Einführung
 Verwendung der Netklassen
 Vergleich zwischen Netklassen und WinInet
 Beschaffenheit der Netklassen
 Interaktion mit Webressourcen
 Interaktion mit vorhandenen Webdiensten
 Nähere Betrachtung der Features
 Schlussfolgerung

Anmerkung Die in diesem Artikel genannte Dokumentation, z.B. das Microsoft .NET Framework SDK, zu dem auch die QuickStart-Dokumentation (in Englisch) gehört, steht auf der CD-ROM "Microsoft PDC Technology Preview Release" zur Verfügung, die Teilnehmer/innen des PDC-Events erhalten.
Anmerkung Dieser Artikel setzt voraus, dass Sie mit den wichtigen Begriffen vertraut sind, die sich auf die Microsoft PDC Technology Preview Release des Microsoft .NET Framework SDKs beziehen, z.B. Active Server Pages+ (ASP+) und die gemeinsame Sprachlaufzeitumgebung.
Anmerkung Der Begriff "Netklassen" in diesem Artikel bezieht sich auf die Gruppe der Klassen, die im System.Net-Namespace des Microsoft .NET Framework SDKs enthalten sind. Diese Begriff sollte nicht mit der Microsoft .NET-Initiative verwechselt werden, die ausführlich unter http://www.microsoft.com/net/default.aspx (in Englisch) beschrieben wird. Netklassen sind nur eine der zahlreichen Technologien, die die Microsoft .NET-Initiative begründen.

Einführung

Ein wichtiges Feature der Microsoft .NET Framework SDK-Technologievorabversion ist ein gemeinsames Framework von Klassen, die eine reichhaltige Plattform zum Erstellen von Anwendungen bieten sollen, die die Laufzeitfeatures des SDKs nutzen. Dieses Framework bietet in den folgenden Bereichen Unterstützung:

  • Daten – Klassen, die XML- und ADO-artige Datenbearbeitungen ermöglichen.

  • Win Forms – Klassen, die das Schreiben von grafischen Windows-Anwendungen vereinfachen, und leistungsstarke Steuerelemente.

  • ASP+ – Unterstützung für die Erstellung serverbasierter Webanwendungen, sowohl Webbenutzeroberfläche (UI in Form von HTML oder WML) als auch XML-Webdienste.

  • Basistypen – Basisklassen, die von dem übrigen Framework für gängige Tasks, z.B. Zeichenfolgen, Auflistungen und Arraybearbeitungen, verwendet werden.

  • Dienste – Unterstützung für die Zusammenarbeit mit Windows-Diensten, Microsoft Message Queue und anderen Features auf Systemebene.

  • Netzwerk – Klassen, die eine Unterstützung zum Erstellen von Anwendungen bieten, die Internetprotokolle zum Senden und Empfangen von Daten verwenden.

In diesem Artikel möchten wir uns das "Innenleben" der Netklassen des Frameworks näher betrachten und uns darauf konzentrieren, wie diese Klassen Sie dabei unterstützen, interessante Anwendungen zu schreiben, die Daten über das Internet senden oder empfangen.

Verwendung der Netklassen

Es gibt eine ganze Bandbreite von Anwendungen, die mit Hilfe von Netklassen geschrieben werden können, aber nur einen fundamentalen Entwurf, der drei Schlüsselziele verfolgt. Ein Verständnis dieser Entwurfsziele ist wichtig, denn Sie erhalten so einen tieferen Einblick, wie diese Klassen wertbringend für Ihre Anwendungen eingesetzt werden können. Keine Sorge, wenn Sie mit einigen der Features nicht vertraut sind! Wir werden diese Features hier Schritt für Schritt behandeln.

  1. Die Netklassen bieten einen einfachen und doch vollständigen Lösungsansatz für das Schreiben von vernetzten Anwendungen in verwaltetem Code. Indem sie ein Schichtenmodell verwenden, statten Netklassen Anwendungen mit der Möglichkeit aus, je nach Bedarf und mit unterschiedlichen Berechtigungsebenen auf das Netzwerk zuzugreifen. Das Spektrum dieser Ebenen deckt nahezu jedes moderne Internetszenario ab – von der feingranularen Kontrolle über Sockets bis zum generischen Anforderung/Antwort-Modell. Außerdem ist das Modell erweiterbar, so dass es auch dann noch funktioniert, wenn sich das Internet längst weiterentwickelt hat.

  2. Die Netklassen legen eine robuste Implementierung des HTTP-Protokolls (Hypertext-Übertragungsprotokoll) offen. Durch den großen Anteil an Verkehr, der im Internet über das HTTP-Protokoll erfolgt, ist seine Bedeutung als Anwendungsprotokoll immens. Die Netklassen unterstützen die meisten der Protokollfeatures von HTTP 1.1. Zu den erweiterten Features zählen Pipelining, Abschnittsbildung, Authentifizierung, Vorauthentifizierung, Verschlüsselung, Proxyunterstützung, Serverzertifikatsüberprüfung, Verbindungsverwaltung und HTTP-Erweiterungen.

  3. Die Netklassen sind für das Schreiben von skalierbaren Hochleistungs-ASP+-Anwendungen der mittleren Ebene ausgelegt. Bei einem gängigen Szenario für heutige Webserver könnten mehrere Anforderungen an Back-End- oder externe Server als Folge einer einzigen Clientbrowseranforderung gerichtet werden. Für dieses Szenario ist ein robuster Middle-tier-Netzwerkstack erforderlich, der hohe Belastungen aushalten kann. Beim Entwurf der Netklassen wurde diese Anforderung seitens des Kunden speziell berücksichtigt. Features wie Verbindungsverwaltung, Pipelining, 'Keep-alives' und asynchrone Senden/Empfangen-Vorgänge stellen eine starke Unterstützung für die mittlere Ebene sicher. Da die Netklassen Teil eines Gesamtframeworks sind, verläuft auch die Integration mit ASP+-Features wie Identitätswechsel und Caching nahtlos.

Vergleich zwischen Netklassen und WinInet

Die Netklassen ähneln der Microsoft WinInet-API darin, dass sie es Anwendungen ermöglichen, Daten über Internetprotokolle zu empfangen und zu senden. Die Netklassen unterscheiden sich jedoch ziemlich in Entwurf und Funktion. Der bedeutsamste Unterschied ist, wie Sie vielleicht der Liste der Entwurfsziele oben entnehmen konnten, dass die Netklassen so entworfen wurden, dass sie den harschen Belastungsbedingungen in der Serverumgebung sicher standhalten.

Beschaffenheit der Netklassen

Lassen Sie uns nun den Code, der für die Netklassen geschrieben wurde, näher untersuchen. Aus logischer Perspektive enthalten die Netklassen drei Schichten: die Anforderung/Antwort-Schicht, die Anwendungsprotokollschicht und die Transportschicht. Die Klassen WebRequest und WebResponse stellen die Anforderung/Antwort-Schicht dar. HTTP-, TCP- (Übertragungssteuerprotokoll-) und UDP (User Datagram Protocol)-Klassen bilden die Anwendungsprotokollschicht, und Sockets die Transportschicht. WebRequest/WebResponse und HTTP befinden sich im System.Net-Namespace, während TCP/UDP und Sockets sich im System.Net.Sockets-Namespace befinden.

Bild01

Abbildung 1. Netklassen

Jede Schicht wird unten durch ein Codebeispiel begleitet, das zeigt, wie die entsprechende Schicht verwendet werden kann.

Anforderung/Antwort-Modell

Das Anforderung/Antwort-Modell befindet sich ganz oben. Es bietet eine einfache Zugriffsmöglichkeit auf Ressourcen im Web. Im folgenden Beispiel wird gezeigt, wie eine Webseite abgerufen und ihr Inhalt in den Bildschirm einer Konsolenanwendung geschrieben wird.

Verwenden von Visual Basic

 ' Einrichten von Variablen, die zum Abrufen des Serverdatenstroms benötigt werden 
Dim WReq As WebRequest 
Dim WResp As WebResponse 
Dim sr As StreamReader 
'  Erstellen des WebRequest-Objekts durch Weiterleiten des URI an die .Create()- 
'  Methode; anschließend Warten auf Antwort durch den Server durch Aufruf von 
'  .GetResponse();  Anmerkung: Zum Erstellen der Anforderung wird immer 
'  WebRequestFactory verwendet. Wir werden uns näher damit beschäftigen,  
'  warum dies so gemacht wird, wenn wir etwas weiter sind 
WReq = WebRequestFactory.Create("http://www.microsoft.com/default.htm") 
WResp = WReq.GetResponse() 
'  Abrufen eines lesbaren Datenstroms vom Server – Verschlüsseln der Daten in ASCII   
'  zum Schreiben auf die Konsole 
sr = new StreamReader(WResp.GetResponseStream(), Encoding.ASCII) 
'  Deklarieren von Variablen zum Lesen von Text         
Dim Buffer(1024) As Char 
Dim bytesread As Integer 
Dim length As Integer 
length = 1024 
'  Lesen vom Datenstrom und Schreiben jeglicher Daten auf die Konsole 
bytesread = sr.Read(Buffer, 0, length) 
Do while (bytesread > 0)  
   Console.Write( Buffer,0, bytesread)    
   bytesread = sr.Read( Buffer, 0, length) 
Loop 
'  Schließen des Datenstroms bei Schleifenende 
sr.Close

Verwenden von C#

// Erstellen des WebRequest-Objekts durch Weiterleiten des URI an die .Create()- 
// Methode; anschließend Warten auf Antwort durch den Server durch Aufruf von 
// .GetResponse();   
WebRequest WReq = WebRequestFactory.Create 
     ("http://www.microsoft.com/default.htm"); 
WebResponse WResp = WReq.GetResponse(); 
// Abrufen eines lesbaren Datenstroms vom Server – Verschlüsseln der Daten in ASCII   
// zum Schreiben auf die Konsole 
StreamReader sr = new StreamReader(WResp.GetResponseStream(),  
     Encoding.ASCII); 
// Deklarieren von Variablen zum Lesen von Text 
int length = 1024; 
char [] Buffer = new char[1024]; 
int bytesread = 0;       
// Lesen vom Datenstrom und Schreiben jeglicher Daten auf die Konsole 
bytesread = sr.Read( Buffer, 0, length); 
while( bytesread > 0 )  
{ 
   Console.Write( Buffer,0, bytesread);    
   bytesread = sr.Read( Buffer, 0, length); 
} 
// Schließen des Datenstroms bei Schleifenende 
sr.Close();            

HTTP-, TCP- und UDP-Klassen

Die HTTP-Klassen implementieren das generische Anforderung/Antwort-Modell und einige zusätzliche Eigenschaften, die eine bessere Kontrollierbarkeit von HTTP-spezifischen Features wie den Zugriff auf das HTTP-Protokoll in einem Objektmodell zum Steuern von Headern oder Abschnitten oder zum Einstellen der Benutzeragentzeichenfolge ermöglichen. In den meisten Fällen reichen WebRequest und WebResponse für das Senden und Empfangen von Daten aus. Die Klassen HttpWebRequest und HttpWebResponse müssen nur verwendet werden, wenn die von WebRequest und WebResponse offen gelegte Detailebene nicht ausreicht. Das folgende Beispiel zeigt, wie einige spezifische HttpWebRequest-Eigenschaften aufgerufen werden, um (in diesem Fall) das HTTP-Keep-alive-Verhalten zu deaktivieren und die Protokollversionsnummer eines Webservers abzurufen.

Verwenden von Visual Basic

'  Für implizites Casten in VB muss die Strict-Option  
'  deaktiviert werden 
Option Strict Off 
Dim HttpWReq As HttpWebRequest 
Dim HttpWResp As HttpWebResponse 
Dim sr As StreamReader 
Dim ver As String 
'  Erstellen des WebRequest-Objekts durch Weiterleiten des URI an die .Create()- 
'  Methode; anschließend Warten auf Antwort durch den Server durch Aufruf von 
'  .GetResponse();  Anmerkung: Zum Erstellen der Anforderung wird immer 
'  WebRequestFactory verwendet. Wir werden uns näher damit beschäftigen,  
'  warum dies so gemacht wird, wenn wir etwas weiter sind 
HttpWReq = WebRequestFactory.Create("http://www.microsoft.com ") 
'  Deaktivieren der Keepalive-Aktivitäten der Verbindung 
HttpWReq.KeepAlive = false 
HttpWResp = HttpWReq.GetResponse() 
'  Ermitteln der HTTP-Protokollversionsnummer, die vom Server zurückgegeben wird 
ver = HttpWResp.Version.ToString 
'  Abrufen eines lesbaren Datenstroms vom Server – Verschlüsseln der Daten in ASCII   
'  zum Schreiben auf die Konsole 
sr = new StreamReader(HttpWResp.GetResponseStream(), Encoding.ASCII) 
…Anschließendes Lesen des Datenstroms, so wie es im WebRequest-Beispiel erfolgte 

Verwenden von C#

// Erstellen des WebRequest-Objekts durch Weiterleiten des URI an die .Create()- 
// Methode; anschließend Warten auf Antwort durch den Server durch Aufruf von 
// .GetResponse(); 
HttpWebRequest HttpWReq = (HttpWebRequest)WebRequestFactory 
     .Create ("http://www.microsoft.com "); 
// Deaktivieren der Keepalive-Aktivitäten der Verbindung 
HttpWReq.KeepAlive = false; 
HttpWebResponse HttpWResp = (HttpWebResponse)HttpWReq.GetResponse(); 
// Ermitteln der HTTP-Protokollversionsnummer, die vom Server zurückgegeben wird 
String ver = HttpWResp.Version.ToString(); 
// Abrufen eines lesbaren Datenstroms vom Server – Verschlüsseln der Daten in ASCII   
// zum Schreiben auf die Konsole 
StreamReader sr = new StreamReader(WResp.GetResponseStream(),  
     Encoding.ASCII); 
…Anschließendes Lesen des Datenstroms, so wie es im WebRequest-Beispiel erfolgte 

TCP und UDP

Zum Schreiben eigener Netzwerkprotokolle, Senden eines UDP-Pakets oder Verwenden von IP Multicast gewähren die TCP- und UDP-Klassen die richtigen Berechtigungsebenen, während dafür gesorgt wird, dass die meisten der Sockets für Sie arbeiten.

Verwenden von Visual Basic

 '  Erstellen eines neuen TCP-Clients 
Dim tcpc As TCPClient 
Dim Buffer(32) As Byte 
Dim bytes As Integer 
Dim server As String 
server = "tcpserver" 
'  Überprüfen, ob der Server vorhanden ist 
if (DNS.GetHostByName(server) = "")  
{ 
            Console.WriteLine("Der Server 'tcpserver' wurde nicht gefunden") 
   return 
} 
'  Verbindungsversuch mit dem Server 
if (tcpc.Connect(server, 13) = -1)  
{ 
   Console.WriteLine("Verbindung zum Server kann nicht hergestellt werden: " + server) 
   return 
} 
'  Abrufen des Datenstroms 
Dim s As Stream 
Dim ServerData as String 
s = tcpc.GetStream         
'  Lesen des Datenstroms und Konvertieren in ASCII 
bytes = s.Read(Buffer, 0, Buffer.Length) 
ServerData = Encoding.ASCII.GetString(Buffer) 
'  Anzeigen der Daten 
Console.WriteLine("Empfangen: " & bytes & " Byte")         
Console.WriteLine("Die vom Server empfangenen Daten sind: " &  
     ServerData)         
'  Schließen des Datenstroms 
tcpc.Close 

Verwenden von C#

// Erstellen eines neuen TCP-Clients 
TCPClient tcpc = new TCPClient();                 
Byte[] read = new Byte[32];         
// Überprüfen, ob der Server vorhanden ist 
if (DNS.GetHostByName("tcpserver") == null)  
{ 
            Console.WriteLine("Der Server 'tcpserver' wurde nicht gefunden"); 
   return; 
} 
// Verbindungsversuch mit dem Server 
if (tcpc.Connect(server, 13) == -1)  
{ 
   Console.WriteLine("Verbindung zum Server kann nicht hergestellt werden: " + server); 
   return; 
} 
// Abrufen des Datenstroms 
Stream s = tcpc.GetStream();         
// Lesen des Datenstroms und Konvertieren in ASCII 
int bytes = s.Read(read, 0, read.Length); 
String ServerData = Encoding.ASCII.GetString(read);         
// Anzeigen der Daten 
Console.WriteLine("Empfangen: " + bytes + " Byte");         
Console.WriteLine("Die vom Server empfangenen Daten sind: " +  
     ServerData);         
// Schließen des Datenstroms 
tcpc.Close(); 

Sockets

Für Entwickler, die sich mit Winsock auskennen oder die Berechtigungsebenen von Sockets nutzen möchten, zeigen die Socket-APIs der Netklassen das gleiche Look & Feel wie die Win32-APIs, die Sie bereits kennen (und auch schätzen?) gelernt haben. Die Sockets-Klassen wirken als Übergangspunkt vom verwalteten zum systemeigenen Code innerhalb der Netklassen. In der Mehrheit der Fälle marshallen die Socket-Aufrufe einfach Daten in ihre systemeigenen Win32-Gegenstücke und führen die ggf. erforderlichen Sicherheitsüberprüfungen durch. Die folgende Beispielfunktion zeigt, wie die Sockets-Klasse verwendet werden kann, um Daten an einen HTTP-Server zu senden und die Antwort zu lesen.

Verwenden von C#

public string DoSocketGet(string server) 
{ 
   // Einrichten von Variablen und einer Zeichenfolge für den Schreibvorgang auf dem Server 
   Encoding ASCII = Encoding.ASCII; 
   string Get = "GET / HTTP/1.1\r\nHost: " + server +  
                   "\r\nVerbindung: Schließen\r\n\r\n"; 
   Byte[] ByteGet = ASCII.GetBytes(Get); 
   Byte[] RecvBytes = new Byte[256]; 
   // IPAddress und IPEndPoint bieten eine Darstellung des  
   // Endpunkts, der die Anforderung empfängt 
   IPAddress hostadd = DNS.Resolve(server); 
   IPEndPoint EPhost = new IPEndPoint(hostadd, 80);             
   StringBuilder sb = new StringBuilder(); 
   // Erstellen des Socket zum Senden von Daten über TCP 
   Socket s = new Socket(AddressFamily.AfINet,  
                 SocketType.SockStream, 
             ProtocolType.ProtTCP); 
   // Herstellen der Hostverbindung über IPEndPoint 
   if (s.Connect(EPhost) != 0)  
   { 
      return "Verbindung zum Host konnte nicht hergestellt werden";           
   }             
   // Senden des GET-Textes an den Host 
   s.Send(ByteGet, ByteGet.Length, 0);             
   // Empfang der Standardseite, Schleife, bis alle Byte empfangen wurden 
   Int32 bytes = s.Receive(RecvBytes, RecvBytes.Length, 0); 
   sb.Append( "Standardmäßige HTML-Seite auf " + server + ":\r\n"); 
   sb.Append( ASCII.GetString(RecvBytes, 0, bytes));             
   while (bytes > 0)  
   { 
      bytes = s.Receive(RecvBytes, RecvBytes.Length, 0); 
      sb.Append( ASCII.GetString(RecvBytes, 0, bytes));          
   } 
   return sb.ToString(); 
}            

Interaktion mit Webressourcen

Die Netklassen wurden entworfen, um Anwendungen die komfortable Interaktion mit Ressourcen im Web zu ermöglichen. Für die Anforderung/Antwort-Klassen müssen diese Ressourcen über URIs adressierbar sein, d.h. über einen Uniform Resource Identifier (genormter Bezeichner zum Auffinden von Ressourcen) aufgelöst werden. Der gebräuchlichste URI im Web ist momentan http://www.<servername>.com/<pfad>. Ressourcen, die URI-adressierbar sind, umfassen statische Seiten, dynamische Seiten, Anwendungen, Daten und Dienste.

Für internetbasierte Anwendungen wie Messengeranwendungen oder Anwendungen wie Napster, die als direkt miteinander kommunizierende Knoten agieren, bieten die TCP- und UDP-Klassen die ideale Schnittstelle.

Daten werden als Datenstrom dargestellt

Wenn Ressourcen im Internet mit Hilfe der Netklassen aufgelöst werden, werden die gesendeten bzw. empfangenen Daten als Stream-Objekte dargestellt. Ihre Anwendung profitiert bei diesem Entwurf von einigen wichtigen Vorteilen.

  • Generische Methode zur Darstellung von Webdaten – Datenströme enthalten eine generische Methode zum Senden und Empfangen von Daten. Sie downloaden z.B. eine GIF-, HTML-, XML- oder andere Datendatei, und Ihre Anwendung verwendet zum Download der Daten die Stream.Read()-Funktion.

  • Volle Unterstützung für Datenströme im Framework – Da Datenströme im gesamten Framework verwendet werden, ist eine weitläufige Infrastruktur aktiv, um diese Datenströme behandeln zu können. Sie können z.B. eine Anwendung bearbeiten, die eine XML-Datei aus einem Dateidatenstrom liest und diese dann verarbeitet, um stattdessen aus einem Netzwerkdatenstrom zu lesen. Dabei müssen Sie nicht einmal viel verändern: lediglich die ein bis zwei Codezeilen, die den Datenstrom abrufen. Wenn Sie jeden dieser Datenströme allgemeiner behandeln, wird die Codebasis schließlich modularer und robuster. Beachten Sie, dass es aufgrund des Unterschieds zwischen Daten, die aus dem Netzwerk stammen, und Daten aus dem lokalen Dateisystem einige Konzepte zu berücksichtigen gilt, wenn Sie mit Netzwerkdatenströmen arbeiten. Die Falle, in die Entwickler am häufigsten tappen, ist der Fehler zu glauben, dass Netzwerkdatenströme nicht so leicht zu identifizieren sind. Da Netzwerkdaten oft dynamisch erzeugt werden, macht es nicht immer Sinn, MyNetStream.Length() zu verwenden. Deshalb hat die Basisklasse Stream im Framework Methoden wie CanSeek, CanRead und CanWrite, die sich als nützlich zum Ermitteln der Möglichkeiten des Datenstroms erweisen und aufgerufen werden sollten, wenn sich die Anwendung nicht von vornherein sicher ist, welchen Datenstromtyp sie verwenden möchte.

Interaktion mit vorhandenen Webdiensten

Dies sollte eigentlich klar sein, aber um sicherzugehen, dass es richtig angekommen ist: Die Netklassen gewähren den Zugriff auf das Netzwerk mit Hilfe von Standardprotokollen, auf denen das Internet aufgebaut ist. Das heißt – vorausgesetzt, Ihre Anwendung weiß, welches Protokoll zu verwenden ist –, eine mit den Netklassen geschriebene Anwendung kann mit beliebigen Anwendungen im Internet kommunizieren, einschließlich der heute im Internet vorhandenen Plattformen und Dienste. Die Netklassen stellen keine zusätzlichen Anforderungen an den Server mit Ausnahme derer, die implizit im verwendeten Protokoll vorliegen. Eine per Netklassen geschriebene Anwendung kann z.B. Daten von einem beliebigen Webserver downloaden, vorausgesetzt, dieser implementiert ordnungsgemäß das HTTP 1.1-Protokoll.

Nähere Betrachtung der Features

Lassen Sie uns jetzt einige der Schlüsselfeatures in den Netklassen untersuchen.

Anforderung/Antwort-Modell

Das Anforderung/Antwort-Modell in den Netklassen wird durch zwei prinzipielle Klassen dargestellt: WebRequest und WebResponse. Diese beiden Klassen bieten eine generische Möglichkeit, auf Ressourcen im Netzwerk zuzugreifen. WebRequest stellt eine Netzwerkanforderung dar und enthält Eigenschaften wie RequestURI, Headers, Credentials und ContentType. Die wichtigsten WebRequest-Methoden sind GetRequestStream, GetResponse und deren asynchrone Gegenstücke, Begin/EndGetRequestStream und Begin/EndGetResponse. Mit GetRequestStream wird ein Datenstrom abgerufen, um Daten auf einen Server zu übertragen. Mit GetResponse wird ein Antwortobjekt vom Server abgerufen. WebResponse stellt die Antwort dar, die ein Server empfängt, der die Anforderung verarbeitet hat. Die wichtigsten Eigenschaften sind ContentLength, ContentType, Headers, ResponseURI und Status. Die gebräuchlichste Methode einer WebResponse-Klasse ist GetResponseStream, die zum Lesen (Downloaden) von Daten vom Server verwendet wird.

Die eigentliche Netzwerkanforderung wird gesendet, wenn der Aufruf an WebRequest.GetResponse erfolgt.

' Erstellen des WebRequest-Objekts durch Weiterleiten des URI an die .Create()- 
' Methode; anschließend Warten auf Antwort durch den Server durch Aufruf von 
' .GetResponse();  Anmerkung: Zum Erstellen der Anforderung wird immer 
' WebRequestFactory verwendet. 
Dim MyUri As String 
Dim WReq As WebRequest 
Dim WResp As WebResponse 
MyUri = "http://www.microsoft.com/default.htm" 
' Erstellen des Request-Objekts 
WReq = WebRequestFactory.Create(MyUri) 
' Senden der Anforderung; Erhalt einer Antwort 
WResp = WReq.GetResponse 

Beim Senden von Daten wird die Anforderung jedoch tatsächlich zu dem Zeitpunkt gesendet, zu dem die Anwendung den Uploaddatenstrom vom Server anfordert.

// Erstellen des WebRequest-Objekts durch Weiterleiten des URI an die .Create()- 
// Methode; anschließend Warten auf Antwort durch den Server durch Aufruf von 
// .GetResponse();  Anmerkung: Zum Erstellen der Anforderung wird immer 
// WebRequestFactory verwendet.  
Dim MyUri As String 
Dim WReq As WebRequest 
Dim RequestStream As Stream 
Dim SomeBytes() As Byte 
Dim payload As String 
' Der URI zum Übertragen der Daten auf den Server 
MyUri = "http://www.meinefirmenuploadsite.com/public/" 
' Dies sind die für den Upload bestimmten Daten. I.d.R. kommen sie 
' aus einer Datenbank, einer Datei oder einem Netzwerkdatenstrom 
payload = "An den Server zu sendende Daten" 
' Erstellen des Request-Objekts 
WReq = WebRequestFactory.Create(MyUri) 
' ASCII verschlüsselt Nutzlast 
SomeBytes = System.Text.Encoding.ASCII.GetBytes(payload)  
' Festlegen einiger der WebRequest-Eigenschaften 
WReq.Method = "POST" 
WReq.ContentType = "application/x-www-form-urlencoded" 
WReq.ContentLength = SomeBytes.Length 
' Abrufen des angeforderten Datenstroms und Schreiben der Daten 
RequestStream = WReq.GetRequestStream 
RequestStream.Write(SomeBytes, 0, SomeBytes.Length) 
RequestStream.Close 

Der Moment, in dem die Anforderung tatsächlich gesendet wird, ist kein Detail, mit dem sich die Anwendung i.d.R. beschäftigen muss, da sie eher an der Antwort interessiert ist. Das Wichtigste ist es für Anwendungsentwickler zu wissen, dass sie eine Antwort erhalten (oder eine Ausnahme, falls etwas nicht funktioniert), wenn die WebRequest.GetResponse-Methode aufgerufen wird.

WebRequest und WebResponse wurden erweiterbar entworfen, um eine Reihe von Internetprotokollen zu unterstützen, z.B. FTP (Protokoll zur Dateiübertragung), HTTP und SMTP (Standard-Mail-Übertragungsprotokoll). Momentan wird HTTP als unterstütztes Protokoll im SDK geführt; FTP wird als "Plug-In-Protokoll" mitgeliefert. Für die Erstellung eines WebRequest wird ein URI in die WebRequestFactory.Create-Methode hinein geleitet. Diese Methode sucht nach dem Schema (z.B. "http:" und "ftp:") des URIs und wählt die zugrunde liegende Implementierungsklasse basierend auf diesem Schema. Für die Anwendung ist dieser Auswahlprozess transparent und bleibt dies auch, sofern die Anwendung nicht auf protokollspezifische APIs für dieses Schema zugreifen muss. Achten Sie beim ursprünglichen Beispiel oben auf den WebRequestFactory.Create()-Aufruf.

' Erstellen des WebRequest-Objekts durch Weiterleiten des URI an die .Create()- 
' Methode; anschließend Warten auf Antwort durch den Server durch Aufruf von 
' .GetResponse();  Anmerkung: Zum Erstellen der Anforderung wird immer 
' WebRequestFactory verwendet. 
Dim MyUri as String 
MyUri = "http://www.microsoft.com/default.htm" 
WReq = WebRequestFactory.Create(MyUri) 

Der Rückgabewert von WebRequestFactory könnte jederzeit in ein HttpWebRequest gecastet werden, aber dies ist i.d.R. nicht notwendig, da die Unterstützung in WebRequest vorliegt.

"Plug-In-Protokolle"

Wenn eine Anwendung nur die WebRequest- und WebResponse-Klassen verwendet, können neue Protokolle wie Plug-Ins aufgesteckt und verwendet werden, ohne dass der Code verändert werden müsste. Durch das Registrieren des URI-Schemas mit WebRequestFactory wird die Protokollunterstützung für die Dauer der Anwendung aufgesteckt. Die Registrierung erfolgt über den Aufruf der WebRequestFactory.Register()-Methode. Diese Methode wird intern für das HTTP-Protokoll aufgerufen, so dass dieses standardmäßig registriert wird; es kann jedoch eine beliebige Zahl zusätzlicher Protokolle im Anschluss daran implementiert und registriert werden. Zugegeben, aufgrund der breiten Palette der Internetprotokolle eignet sich dieses Modell nicht für alle Szenarios. Protokolle, die Chatsitzungen regeln oder dem Anforderung/Antwort-Modell nicht auf andere Weise förderlich sind, können lieber mit TCP- oder UDP-Klassen oder in einigen Fällen auch über die Sockets-Klassen implementiert werden. Wenn Sie nicht sicher sind, welche Ebene für Sie die richtige ist, beginnen Sie erst einmal mit dem Anforderung/Antwort-Modell, und gehen Sie dann den Stapel nach unten bis zu Sockets durch, wenn das Anforderung/Antwort-Modell nicht Ihren Erwartungen entspricht.

HTTP

Die robuste Unterstützung des HTTP-Protokolls hatte in den Entwurfs- und Implementierungsphasen der Netklassen höchste Priorität. Die unten beschriebenen APIs zeigen, wie Sie zu einigen der erweiterten Features von HTTP vorstoßen.

Abschnittsbildung

Die Abschnittsbildung ist nützlich, wenn eine Anwendung Daten senden oder empfangen muss, deren exakte Größe zum Zeitpunkt des Download-/Uploadstarts unbekannt ist. Dies kommt nicht selten vor, wenn die zur Übertragung bereitstehenden Daten dynamisch basierend auf sonstiger Anwendungs- oder Serverlogik erstellt werden. Zum Senden von abschnittsunterteilten Daten muss WebRequest in ein HttpWebRequest gecastet und die HttpWebRequest.SendChunked-Eigenschaft auf TRUE gesetzt werden.

' Für implizites Casten in VB muss die Strict-Option  
' deaktiviert werden 
Option Strict Off 
Dim MyUri As String 
Dim HttpWReq As HttpWebRequest 
Dim RequestStream As Stream 
' Der URI zum Übertragen der Daten auf den Server 
MyUri = "http://www.meinefirmenuploadsite.com/public/" 
' Erstellen des Request-Objekts 
HttpWReq = WebRequestFactory.Create(MyUri) 
' Festlegen einiger der WebRequest-Eigenschaften 
HttpWReq.Method = "POST" 
HttpWReq.ContentType = "text/xml" 
HttpWReq.SendChunked = True 
' Abrufen des angeforderten Datenstroms und Schreiben der Daten 
RequestStream = HttpWReq.GetRequestStream 
…Hier würden Sie eine Schleife durch das Lesen der dynamischen Daten und Schreiben  
in RequestStream durchführen 
' Schließen des Datenstroms bei Beendigung – Dies ist besonders wichtig,  
' wenn Abschnitte gesendet werden, da diese Anweisung dem Server mitteilt, 
' dass Sie fertig sind 
RequestStream.Close 

HTTP-Pipelining

Pipelining ist ein HTTP 1.1-Feature, das es den Netklassen ermöglicht, mehrere HTTP-Anforderungen an einen Back-End-Server über eine persistente Verbindung zu senden, ohne auf eine Antwort vom Server zu warten, bevor die nächste Anforderung gesendet wird. Dies kann erhebliche Leistungsverbesserungen bringen, da Anwendungen, die mehrere Ressourcen von einem Server anfordern, nicht durch das Warten auf eine bestimmte Ressource blockiert werden, die u.U. einen zeitraubenden Vorgang auf dem Server (z.B. einen Datenbankaufruf) auslösen. In Abbildung 2 wird die Verwendung des Pipelining verglichen mit dem herkömmlichen Anforderung/Antwort-Verhalten von HTTP demonstriert. Beim Pipelining (rechts) werden Sie feststellen, dass die Gesamtzeit für die Verarbeitung aller drei Anforderungen reduziert wird, weil eben der Client seine Anforderungen sendet, bevor die Antworten empfangen werden.

Bild02

Abbildung 2. Pipelining kontra herkömmliches Anforderung/Antwort-Verhalten von HTTP

In den Netklassen läuft das Pipelining standardmäßig im Hintergrund ab. Durch das Setzen der HttpWebRequest.Pipelined-Eigenschaft auf FALSE wird das Pipelining für bestimmte Situationen deaktiviert, in denen eine Verwendung nicht wünschenswert wäre.

' Für implizites Casten in VB muss die Strict-Option  
' deaktiviert werden 
Option Strict Off 
Dim MyUri As String 
Dim HttpWReq As HttpWebRequest 
' Der anzufordernde URI 
MyUri = "http://www.meinefirmenuploadsite.com/public/" 
' Erstellen des Request-Objekts 
HttpWReq = WebRequestFactory.Create(MyUri) 
' Deaktivieren des Pipelining 
HttpWReq.Pipelined = False 

Verbindungsverwaltung

Keep-Alive – Das Keep-Alive-Feature wurde im HTTP 1.0-Protokoll eingeführt, um es einem HTTP verwendenden Client zu ermöglichen, Netzwerkressourcen zu schonen und effizienteres Verhalten zu zeigen. Dazu wird die vorhandene TCP-Verbindung zum Server am Leben ('alive') erhalten und wieder verwendet und nicht geschlossen und neu für jede Anforderung erstellt. Standardmäßig ist die Keep-Alive-Eigenschaft auf TRUE gesetzt, und es wird eine persistente Verbindung zum Server aufgebaut, vorausgesetzt, der Server unterstützt dieses Verhalten. Wenn Sie von einer Middle-tier-ASP+-Anwendung auf einen Back-End-Server zugreifen, sollten Sie sich im Klaren sein, dass die Verbindung zu diesem Back-End-Server solange aufrechterhalten bleibt, bis der Back-End-Server das Verbindungstimeout überschreitet.

Höchstanzahl an Verbindungen – Die Verbindungsverwaltung ist ein wichtiges Feature zum Erreichen optimaler Skalierung und Leistung in einer vernetzten Anwendung. Die Anzahl an Verbindungen zwischen zwei Computern kann eine beträchtliche Auswirkung auf den Durchsatz der Anwendung haben. Die standardmäßige Anzahl an Verbindungen von einer Anwendung, die die Netklassen verwendet, zu einem Server beträgt zwei. Diese Anzahl kann je nach Anwendung erhöht oder verringert werden. Die Abbildung unten zeigt drei Clients, die eine Verbindung zu einem ASP+-Server haben. Jeder Client hat zwei Verbindungen. Der Server antwortet über sechs Verbindungen einem Back-End-Computer.

Bild03

Abbildung 3. Drei Clients mit einer ASP+-Server-Verbindung (jeder Client nutzt zwei Verbindungen)

Die optimale Anzahl von Verbindungen hängt von dem Szenario ab, in dem die jeweilige Anwendung ausgeführt wird. Geben Sie also keine spezifische Verbindungsempfehlung aus, sondern führen Sie zunächst einmal eine Baselinemessung des Anwendungsdurchsatzes mit den Voreinstellungen aus, und ändern Sie dann die Voreinstellungen. Betrachten Sie, wie sich die Leistung verändert. Beispiel: Wenn die Voreinstellung zwei ist, können Sie sie probeweise in vier ändern. Im Allgemeinen sollte die Anzahl an gleichzeitigen Verbindungen nicht in die Hunderte gehen, da es ein fein ausgewogenes Mischungsverhältnis zwischen den Vorteilen, die die Anwendung aus mehreren Verbindungen bezieht, und dem Overhead gibt, der beim Erstellen einer neuen Verbindung anfällt. An einem bestimmten Punkt sinkt die Leistung einer Anwendung, die viele Verbindungen erstellt, unter das Maß einer Anwendung, die die vorhandenen Verbindungen sinnvoll nutzt. Die gute Nachricht für Sie ist, dass die Netklassen in den meisten Fällen "das Richtige" für Sie tun. Entwickler, die die asynchronen APIs oder die synchronen APIs in Multithreadweise verwenden, können die Verbindung über die statische ServicePoint.DefaultPersistentConnectionLimit-Eigenschaft ändern.

' Rufen Sie diesen Code bei Anwendungsinitialisierung auf, wenn Sie  
' die Voreinstellung von 2 in 4 ändern möchten – Anmerkung: 2 ist  
' in vielen Fällen die optimale Anzahl an Verbindungen 
System.Net.ServicePoint.DefaultPersistentConnectionLimit = 4 

Verbindungsgruppen – Verbindungsgruppen in den Netklassen bieten eine Möglichkeit, spezifische Anforderungen innerhalb einer einzigen Anwendung mit einem definierten Verbindungs-Pool zu verknüpfen. Dies ist besonders dann hilfreich, wenn die Authentifizierung auf Verbindungsebene verwendet wird und viele Anforderungen von einer Middle-tier-Anwendung an einen Back-End-Computer gesendet werden. Oftmals ist es wünschenswert, dass die Verbindung, über die solche Anforderungen gehen, mit einem Benutzer verknüpft wird. Angenommen, der Benutzer Hans besucht eine interne Website, die seine Gehaltsinformationen anzeigt. Beim ersten Aufruf der Site wird Hans aufgefordert, sich mit einer Domäne, seinem Benutzernamen und seinem Kennwort anzumelden. Im Hintergrund stellt die Website, die Hans besucht, eine HTTP-Anforderung an einen anderen Back-End-Computer, um mit Hans' Windows NT-Anmeldeinformationen eine Datei abzurufen, die seinem Profil entspricht. Hans' Profil wird dann verwendet, um die Gehaltsinformationen abzurufen. In vielen Fällen erfolgt eine Authentifizierung dieser Back-End-Anforderung mit dem Microsoft NTLM-Protokoll (NT LAN-Manager), so dass die Verbindung jetzt mit Hans' Anmeldeinformationen authentifiziert ist. Als Nächstes besucht Dorothea die Site und möchte ihre Gehaltsinformationen einsehen. Da aber die Back-End-Verbindung als Hans authentifiziert ist, antwortet der Back-End-Server mit Hans' Profil. Obwohl ein bißchen extrem, soll Ihnen dieses Beispiel demonstrieren, wie wichtig es ist, einige Anforderungstypen in Verbindungsgruppen aufzuteilen. Dazu setzt die Anwendung einfach die WebRequest.ConnectionGroupName-Eigenschaft, bevor sie die Anforderung stellt.

' Erstellen des WebRequest-Objekts durch Weiterleiten des URI an die .Create()- 
' Methode. Anmerkung: Zum Erstellen der Anforderung wird immer 
' WebRequestFactory verwendet. 
Dim MyUri as String 
Dim WReq As WebRequest 
MyUri = "http://www.microsoft.com/default.htm" 
WReq = WebRequestFactory.Create(MyUri) 
WReq.ConnectionGroupName = "Hans" 

Authentifizierung

Die Netklassen unterstützen eine Vielzahl von Clientauthentifizierungsmechanismen, darunter Digestauthentifizierung, Standardauthentifizierung, Kerberos-Authentifizierung, NTLM-Authentifizierung und benutzerdefinierte Authentifizierung. Eine Authentifizierung wird erreicht, indem das WebRequest.Credentials-Objekt vor dem Stellen einer Anforderung eingestellt wird. Bei der Digest- und Standardauthentifizierung werden Benutzername und Kennwort angegeben. Für die NTLM- und Kerberos-Authentifizierung wird die Sicherheit von Windows verwendet, und das Credential-Objekt kann auf einen Benutzernamen, ein Kennwort oder eine Domänenkombination gesetzt werden, oder es können die Systemvoreinstellungen angefordert werden.

' Stellen einer Anforderung an eine interne Site über NTLM  
Dim MyUri as String 
Dim WReq As WebRequest 
MyUri = "http://gehaltsinfo/default.aspx" 
WReq = WebRequestFactory.Create(MyUri) 
WReq.Credentials = CredentialCache.DefaultCredentials 

Eine Anforderung an eine Internetsite über die Standardauthentifizierung würde folgendermaßen aussehen:

' Stellen einer Anforderung an eine geschützte interne Site über NTLM 
Dim MyUri as String 
Dim WReq As WebRequest 
MyUri = "http://www.standardsite.com/default.aspx" 
WReq = WebRequestFactory.Create(MyUri) 
WReq.Credentials = new SingleCredential("username", "password) 

Secure Socket Layer (SSL)

Die Unterstützung für geschützte (SSL 3.0-) Verbindungen erfolgt in den Netklassen nahtlos. Wenn das https://-Schema am Anfang des URI verwendet wird, verwenden die Klassen im Verborgenen SSL.

' Stellen einer Anforderung an eine Site über SSL – beachten Sie den HTTPS-URI 
Dim MyUri as String 
Dim WReq As WebRequest 
Dim WResp As WebResponse 
MyUri = "https://www.sslsite.com/default.aspx" 
WReq = WebRequestFactory.Create(MyUri) 
WResp = WReq.GetResponse 

Proxyunterstützung

Die HTTP-Proxyunterstützung in den Netklassen kann per Anforderung gesteuert werden oder einmal global für die gesamte Lebensdauer der Anwendung gesetzt werden. Das folgende Beispiel zeigt, wie der Proxy global eingestellt werden kann, wenn die Anforderung durch einen Proxyserver geht.

' Stellen einer Anforderung an eine externe Site über einen Proxyserver 
Dim MyUri as String 
Dim WReq As WebRequest 
Dim WResp As WebResponse 
Dim proxyObject as DefaultControlObject 
proxyObject = new DefaultControlObject("meinproxyservername", 80) 
' Deaktivieren des Proxies, wenn der Host lokal ist (keine Punkte). 
proxyObject.ProxyNoLocal = true 
' Mit den jetzigen Einstellungen global werden. Alle neuen  
' Anforderungen müssen diese Proxyinformationen verwenden 
GlobalProxySelection.Select = proxyObject 
MyUri = "https://www.externesite.com/default.aspx" 
WReq = WebRequestFactory.Create(MyUri) 
WResp = WReq.GetResponse 

TCP und UDP

Die im System.Net.Sockets-Namespace verfügbaren Klassen TCPClient, TCPListener und UDPClient bieten Unterstützung für die Protokolle TCP und UDP.

TCPClient

Die TCPClient-Klasse bietet einen einfachen Weg, eine Verbindung zu einem Endpunkt über das TCP-Protokoll herzustellen. Sie legt außerdem Daten offen, die über die Verbindung von einem NetworkStream-Objekt gelesen oder geschrieben werden. Weitere Informationen finden Sie im nun folgenden Datum/Zeit-Clientbeispiel, das der QuickStart-Dokumentation entnommen wurde.

Geschrieben mit C#

using System; 
using System.Net; 
using System.Net.Sockets; 
using System.IO; 
using System.Text; 
class Client  
{ 
   public static void Main(String[] args)  
   { 
      TCPClient tcpc = new TCPClient();                 
      Byte[] read = new Byte[32];         
      if (args.Length != 1)  
      { 
                  Console.WriteLine("Geben Sie einen Servernamen 
                                      in der Befehlszeile an"); 
                  return; 
      } 
      String server = args[0]; 
      // Überprüfen, ob der Server vorhanden ist 
      if (DNS.GetHostByName(server) == null)  
      { 
                  Console.WriteLine("Server wurde nicht gefunden: " +  
                                     server); 
                  return; 
      } 
      // Verbindungsversuch mit dem Server 
      if (tcpc.Connect(server, 13) == -1)  
      { 
             Console.WriteLine("Verbindung zum Server kann nicht hergestellt werden: " + server); 
                  return; 
      } 
      // Abrufen des Datenstroms 
      Stream s = tcpc.GetStream();         
      // Lesen des Stroms und Konvertieren in ASCII 
      int bytes = s.Read(read, 0, read.Length); 
      String Time = Encoding.ASCII.GetString(read);         
      // Anzeigen der Daten 
      Console.WriteLine("Empfangen: " + bytes + " Byte");      
      Console.WriteLine("Datum/Zeit: " + Time);      
      tcpc.Close(); 
   } 
}  

TCPListener

Die TCPListener-Klasse vereinfacht das Abhören eines bestimmten Sockets für eine TCP-Verbindung vom Client. Weitere Informationen finden Sie im nun folgenden Datum/Zeit-Serverbeispiel, das der QuickStart-Dokumentation entnommen wurde.

Geschrieben mit C#

using System; 
using System.Net; 
using System.Net.Sockets; 
using System.Text; 
class Server  
{ 
   public static void Main()  
   { 
      DateTime now;     
      String strDateLine;       
      Encoding ASCII = Encoding.ASCII; 
      // Überwachen von Anschluss 13    
      TCPListener tcpl = new TCPListener(13);    
      tcpl.Start(); 
      Console.WriteLine("Warte auf Clients, die eine Verbindung herstellen..."); 
         Console.WriteLine("Drücken Sie STRG+C, um den Vorgang abzubrechen..."); 
      while (true) 
      { 
         // Accept wird gesperrt, bis jemand eine Verbindung herstellt 
                  Socket s = tcpl.Accept(); 
         // Abrufen von Datum/Zeit; anschließend verketten  
                  // into a string 
                  now = DateTime.Now; 
                  strDateLine = now.ToShortDateString() + " " +  
                  now.ToLongTimeString(); 
                  // Konvertieren der Zeichenfolge in ein Bytearray und Senden 
                  Byte[] byteDateLine =  
ASCII.GetBytes(strDateLine.ToCharArray()); 
         s.Send(byteDateLine, byteDateLine.Length, 0); 
         Console.WriteLine("Gesendet " + strDateLine); 
      } 
   } 
} 

UDPClient und Multicast

Die UDPClient-Klasse vereinfacht das Senden von Netzwerkdatagrammen und IP Multicasts mit Gruppenverwaltungsmethoden wie UDPClient.JoinMulticastGroup und UDPClient.DropMulticastGroup.

Codezugriff

Mit den Klassen WebPermissions bzw. SocketPermissions kann eine Anwendung berechtigt werden, eingehende Verbindungen zu akzeptieren bzw. Verbindungen zu anderen Hosts basierend auf URIs oder Transportadressen herzustellen. Die beiden Berechtigungen haben die gleichen Richtlinien für das Gewähren bzw. Verweigern von Zugriff, werden jedoch als zwei unterschiedliche APIs dargestellt, da sie auf zwei unterschiedlichen Abstraktionsebenen agieren. WebPermissions und SocketPermissions können sowohl in Kombination als auch individuell verwendet werden.

WebPermissions

Die WebPermissions-Klasse steuert die Rechte einer Anwendung zum Zugriff oder Export eines URI.

SocketPermissions

Die SocketPermissions-Klasse steuert die Rechte einer Anwendung zur Annahme von Verbindungen auf einer lokalen Transportadresse und zur Kontaktaufnahme zu anderen Anwendungen bezüglich Transportadressen, die durch einen Hostnamen, eine Anschlussnummer und einen Transport beschrieben werden.

Schlussfolgerung

Weitere Informationen zu Netklassen und anderen interessanten Entwicklerfeatures erhalten Sie auf der Microsoft Professional Developer's Conference. Wir sehen uns dort!


Anzeigen: