communityWir suchen ständig neue Tutorials und Artikel! Habt ihr selbst schonmal einen Artikel verfasst und seid bereit dieses Wissen mit der Community zu teilen? Oder würdet ihr gerne einmal über ein Thema schreiben das euch besonders auf dem Herzen liegt? Dann habt ihr nun die Gelegenheit eure Arbeit zu veröffentlichen und den Ruhm dafür zu ernten. Schreibt uns einfach eine Nachricht mit dem Betreff „Community Articles“ und helft mit das Angebot an guten Artikeln zu vergrößern. Als Autor werdet ihr für den internen Bereich freigeschaltet und könnt dort eurer literarischen Ader freien Lauf lassen.

TCP/IP Socket-Programmierung in C# - Daten senden und empfangen Drucken E-Mail
Benutzerbewertung: / 982
SchwachPerfekt 
Geschrieben von: Kristian   
Sonntag, den 12. März 2006 um 02:20 Uhr
Beitragsseiten
TCP/IP Socket-Programmierung in C#
Daten senden und empfangen
Höhere Socketklassen
Multicast und Broadcast
Ping, Threads und asynchrone Sockets
Formulare im Internet senden
E-Mail verschicken
Alle Seiten

Daten senden und empfangen

Bisher haben sich alle Programme darauf beschränkt Hosts aufzulösen, Sockets zu öffnen, anschließend wieder zu schließen oder einfache Informationen zu IP-Adressen auszugeben. Nun führen wir die Sockets ihrem eigentlichen Zweck zu und werden mit ihrer Hilfe Daten senden und empfangen.

Um Daten synchron über das Netzwerk zu senden stellt die Socket Klasse die Methode Send bereit. Die Methode Send ist mehrfach überladen und nimmt unterschiedliche Kombinationen an Parametern entgegen. Nachfolgend werden alle Send Methoden des .NET Frameworks 2.0 aufgelistet:

public int Send(byte[] buffer);
public int Send(byte[] buffer, SocketFlags socketFlags);
public int Send(byte[] buffer, int size, SocketFlags socketFlags);
public int Send(byte[] buffer, int offset, int size, SocketFlags socketFlags);

Eines haben alle vier Implementierungen gemein. Sie erwarten ein byte[] Array das die Daten beinhaltet die übertragen werden sollen. Zudem geben alle Methoden die Anzahl der gesendeten Bytes als Integer zurück. Die Methoden sind gestaffelt und erweitern die Parameterliste mit jeder Überladung um einen neuen Parameter. Wir wenden uns deshalb gleich der vierten Überladung zu.

public int Send(byte[] buffer, int offset, int size, SocketFlags socketFlags);

Während der erste Parameter buffer die Daten selbst beinhaltet, gibt der Integer Parameter offset die Stelle im byte[] buffer an ab welchem begonnen wird die Daten zu senden. Der zweite Integer Parameter size gibt die Anzahl der zu sendenden Daten an. Als letzter Parameter spezifiziert socketFlags die bitweise Kombination der System.Net.Sockets.SocketFlags Enumerationen Member. Das sind unter Anderen None (keine besonderen Flags beim Aufruf verwenden) und DontRoute (sende ohne die Nutzung von Routing Tabellen). In der Regel werden keine besonderen Flags bei gängigen Übertragungen gesetzt.

Neben der Methode Send benötigen wir noch die Methode Receive um Daten zu empfangen. Receive ist aufgrund der Symmetrie ebenfalls vierfach überladen.

public int Receive(byte[] buffer); 
public int Receive(byte[] buffer, SocketFlags socketFlags); 
public int Receive(byte[] buffer, int size, SocketFlags socketFlags); 
public int Receive(byte[] buffer, int offset, int size, SocketFlags socketFlags);

Ein guter Weg festzustellen ob sich nach einem Aufruf der Methode Receive Daten in der Warteschlange befinden ist die Eigenschaft Available. Bei Stream Sockets sind die verfügbaren Daten die totale Anzahl an zu lesenden Daten im Puffer (engl. Buffer). Bei Datagram Sockets repräsentiert Available die erste Nachricht im Buffer. Falls sich keine Daten in der Warteschlange befinden wird 0 zurückgegeben.

Die beiden Methoden Send und Receive sind elementare Eigenschaften eines Socket und stehen sowohl unter TCP, als auch unter UDP zur Verfügung. Je nach eingesetztem Protokoll kann ihr Verhalten voneinander abweichen.

Client-Server Programmierung in .NET

Das Internet wird oft auch als ein Client-Server-System bezeichnet. Ihr Computer ist in der Regel der Client während die entfernten Rechner, die die Daten liefern meist die Rolle des Servers übernehmen. Wir haben bereits in einem vorangegangenen Abschnitt erfahren worin der genaue Unterschied zwischen einem Clienten und einem Server liegt.

clientserver

Die Server Dienste laufen auf fest definierten Ports, die bekanntermaßen dem Clienten bekannt sein müssen. Der Client startet die Kommunikation mit dem Server der passiv darauf wartet kontaktiert zu werden. Die Kommunikation zwischen Client und Server ist abhängig vom Dienst, d. h. der Dienst bestimmt, welche Daten zwischen beiden ausgetauscht werden. Der Server ist in Bereitschaft, um jederzeit auf die Kontaktaufnahme eines Clients reagieren zu können. Im Unterschied zum Client, der aktiv einen Dienst anfordert, verhält sich der Server passiv und wartet auf Anforderungen. Die Regeln der Kommunikation für einen Dienst (Format, Aufruf des Servers, und die Bedeutung der zwischen Server und Client ausgetauschten Daten), werden durch ein Protokoll festgelegt, und das Protokoll ist spezifisch für den jeweiligen Dienst.

Transmission Control Protocol (TCP)

Bevor ein Softwareentwickler ernsthaft darüber nachdenken kann Client-Server-Anwendungen zu entwickeln, muss er sich mit dem verwendeten Transportprotokoll auseinandersetzen. Er muss wissen, welche Vor- und Nachteile das verwendete Protokoll hat und natürlich wie das Protokoll funktioniert. Sie haben im Abschnitt Grundlagen bereits ein paar Informationen über das TCP und UDP erhalten, diese Kenntnisse sollen nun vertieft werden. Wir beginnen mit dem wichtigsten Transportprotokoll für das Internet, dem TCP. Das Transmission Control Protocol (TCP) (zu dt. Übertragungssteuerungsprotokoll) ist eine Vereinbarung (Protokoll) darüber, auf welche Art und Weise zwei Kommunikationspartner miteinander kommunizieren. Alle Betriebssysteme moderner Computer beherrschen TCP und nutzen es für den Datenaustausch mit anderen Rechnern. Das Protokoll ist ein zuverlässiges, verbindungsorientiertes, paketvermittelndes Transportprotokoll in Computernetzwerken. Es ist in Schicht 4 des OSI-Referenzmodells angesiedelt. Das TCP unterscheidet deutlich zwischen Client- und Server-Diensten.

Das Transmission Control Protocol (TCP) ist ein verbindungsorientiertes Protokoll, welches auf Zuverlässigkeit ausgelegt ist und einen bidirektionalen, byte-orientierten Datenstrom zwischen zwei Endpunkten etabliert. Die Daten der Pakete werden beim Empfänger in einem Puffer in der richtigen Reihenfolge zu einem Datenstrom zusammengefügt und doppelte Pakete verworfen. TCP prüft die Integrität der Daten und sendet verloren gegangene Pakete erneut zu.

Das .NET Framework stellt die Klassen TcpClient und TCPListener zur Verfügung, die sich in der Abstraktionsschicht eine Stufe über der Socket Klasse befinden und auf einfache Art und Weise die Implementierung einer Client-Server-Anwendung mit TCP ermöglichen. Bevor wir diese beiden Klassen jedoch verwenden, werden wir einen einfachen Echo-Server mit Hilfe der bereits bekannten und funktionelleren Socket-Klasse realisieren.

Ein Echo-Server ist, wie sein Name schon andeutet, ein Server der nichts anderes macht als die ihm zugesandten Daten wieder an den Clienten zurück zu schicken, so wie die Flächen von Felswänden Schallwellen verzögert reflektieren. Da der Server indirekt die Spielregeln in der Kommunikation über TCP bestimmt - er bietet an fest definierten Ports seine Dienste an - beginnen wir mit der Erstellung eines TCP-Echo-Servers. Ein Standard Echo Dienst läuft auf dem Port 7. Mit den uns bekannten Funktionen lässt sich der TCP-Server bereits zu 95% umsetzen. Lediglich zwei weitere Methoden der Socket Klasse werden benötigt um das Programm zu komplettieren. Die erste Methode ist

public void Bind(
   EndPoint localEP
);

Der Aufruf von Bind assoziiert den Socket mit einem bestimmten Endpunkt. Die Methode wirft neben einer SocketException auch eine ObjectDisposedException. Die Methode Bind kann sowohl bei verbindungsorientierten als auch bei verbindungslosen Protokollen verwendet werden. Nachdem der Socket mit einem Endpunkt assoziiert wurde, kann die zweite elementare Methode namens Listen aufgerufen werden.

public void Listen(
   int backlog
);

Listen ändert den Status des Sockets, so dass an diesem auf eingehende TCP Verbindungen gehorcht (engl. listen) wird. Der backlog Parameter spezifiziert die maximale Anzahl an eingehenden Verbindungen die in die Warteschlange eingereiht werden können. Um die maximal unterstützte Anzahl an eingehenden TCP Verbindungen die ihr System zulässt festzulegen, können Sie auf die Enumeration MaxConnections zurückgreifen. Diese kann über die Methode Socket.SetSocketOption gesetzt werden. Der TCP-Echo-Server könnte zum Beispiel so aussehen:

using System;
using System.IO;
using System.Net;
using System.Text;
using System.Net.Sockets;
 
namespace CodePlanet.Articles.ProgrammingSockets
{
    /// <summary>
    /// Ein synchroner TCP-Server, der alle empfangenen Daten
    /// wieder umgehend an den Clienten zurück sendet.
    /// </summary>
    public class TCPEchoServerSocket
    {
        public static void Main(string[] args)
        {
            if (args.Length > 1) {
                throw new ArgumentException("Parameters: [<Port>]");
            }
 
            int servPort = (args.Length == 1) ? Int32.Parse(args[0]) : 7;
 
            Socket servSock = null;
 
            try {
                // Verwende explizit IPv6
                servSock = new Socket(AddressFamily.InterNetworkV6,
                                      SocketType.Stream,
                                      ProtocolType.Tcp);
 
                // Assoziiert den Socket mit einem lokalen Endpunkt
                servSock.Bind(new IPEndPoint(IPAddress.IPv6Any, servPort));
 
                // Versetzt den Socket in den aktiven Abhörmodus 
                servSock.Listen(BACKLOG);
            } catch (SocketException se) {
                Console.WriteLine(se.ErrorCode + ": " + se.Message);
                Environment.Exit(se.ErrorCode);
            }
 
            byte[] rcvBuffer = new byte[BUFSIZE];
            int bytesRcvd;
 
            // Lässt den Server in einer Endlosschleife laufen
            for (; ; ) {
                Socket client = null;
 
                try {
                    client = servSock.Accept();
 
                    Console.Write("Handling client at " + client.RemoteEndPoint + " - ");
 
                    // Empfange bis der client die Verbindung schließt, das geschieht indem 0
                    // zurückgegeben wird
                    int totalbytesEchoed = 0;
                    while ((bytesRcvd = client.Receive(rcvBuffer, 0, rcvBuffer.Length,
                                                       SocketFlags.None)) > 0) {
                        client.Send(rcvBuffer, 0, bytesRcvd, SocketFlags.None);
                        totalbytesEchoed += bytesRcvd;
                    }
                    Console.WriteLine("echoed {0} bytes.", totalbytesEchoed);
 
                    client.Shutdown(SocketShutdown.Both);
                    client.Close();
                } catch (Exception e) {
                    Console.WriteLine(e.Message);
                    client.Close();
                }
            }
        }
 
        private const int BUFSIZE = 32;
        private const int BACKLOG = 5;
    }
}

Im ersten Teil des Programms wird der Socket initialisiert, gebunden und in den Listening Status versetzt. Scheitert eine Methode, wird eine SocketException ausgelöst, anschließend Exit aus der Klasse System.Environment aufgerufen die den aktuellen Prozess beendet und die Kontrolle an das Betriebssystem zurückgibt.

Im zweiten Teil wird der Server in eine Endlosschleife versetzt, so dass dieser ununterbrochen auf neue eingehende Verbindungen wartet. Die Methode Accept generiert einen neuen Socket indem sie synchron die anstehenden Verbindungsanfragen aus der Warteschlange des Listening Sockets extrahiert.

Ein weiteres Novum im Code ist die Methode Shutdown aus System.Net.Sockets.Socket. Wenn Sie einen verbindungsorientierten Socket verwenden, sollten Sie stets die Shutdown Methode aufrufen bevor Sie den Socket schließen. Das garantiert das alle Daten am verbundenen Socket gesendet und empfangen werden bevor der Socket geschlossen wird. Nachdem der TCP-Echo-Server alle Daten empfangen und umgehend an den Clienten zurück gesendet hat, gibt das Programm die Anzahl der Daten in Bytes mit WriteLine aus.

Paketsegmentierung

Da es sich beim IP um ein paketorientiertes Protokoll handelt, werden Anwendungsdaten, die über das Internet übertragen werden, in kleine TCP-/IP-Pakete aufgeteilt. Um beispielsweise mit einem 1460 Byte großen Nutzdatenfeld 10 Kilobyte Daten zu versenden, teilt man die Daten auf mehrere Pakete auf, fügt einen Header hinzu und versendet die TCP-Segmente. Dieser Vorgang wird Segmentierung genannt. Jedes Segment ist nummeriert, so dass die Pakete beim Empfänger wieder nach ihrer Reihenfolge sortiert werden können. Die Maximum Segment Size (MSS) definiert in einem Rechnernetz die maximale Anzahl von Bytes, die als Nutzdaten in einem TCP-Segment versendet werden können. Der Vorgang der Datenübertragung über TCP mit Nutzdaten beliebiger Länge kann durch eine Zerlegung in Segmente beschrieben werden. Die TCP-Segmente mit dem TCP-Kopfbereich werden im OSI-Schichtenmodell nach unten zur Vermittlungsschicht weitergereicht, dort in einem IP-Paket verpackt, anschließend in der Sicherungsschicht in einem Ethernet-Frame eingebettet, so dass das Paket seine Reise durch das Internet antreten kann.

Das nachfolgende Diagramm skizziert diesen Vorgang der Segmentierung. Ein Datenpaket mit vielen TCP-Nutzdaten wird abhängig von der MSS vor der Übertragung in mehrere kleine Pakete aufgeteilt.

segmentation

Das Lesen der Anwendungsdaten beim Empfänger geschieht deshalb nicht zwangsläufig in einem Schritt, da der Empfänger die Daten in Form von diskreten Paketen mit einer spezifischen Größe, nämlich der maximalen Segmentgröße (MSS), erhält. In der Vermittlungsschicht begrenzt zudem die Maximum Transmission Unit (MTU) die zu übermittelnde Paketgröße. Das bedeutet, dass ein einzelner Aufruf von Send oder zum Beispiel Write nicht unbedingt in einem Receive- bzw. Read-Aufruf endet. Das TCP-Protokoll hält sich nicht an irgendwelche Begrenzungen in den Nachrichten und kann deshalb vereinzelte Übertragungen nicht auseinanderhalten. Das Protokoll stellt lediglich sicher, dass alle Pakete ankommen und beim Empfänger wieder korrekt zusammengefügt werden. Ein einzelner Aufruf zum Senden von Daten über Send kann auch von der Gegenstelle in mehreren Receive-Aufrufen abgearbeitet werden. Denn der Server liest die eingehenden Daten nicht direkt aus dem Netzwerk sondern aus dem internen TCP-Buffer und dieser füllt sich in unregelmäßigen Abständen mit den Daten des Senders, ähnlich einem Staubecken, das sich mit Wasser füllt. Alle eingehenden TCP-Pakete werden sequentiell in eine Warteschlange eingereiht. Sobald die Methode Receive oder eine vergleichbare Methode zum Auslesen des TCP-Buffer's aufgerufen wird, liest die Methode die Daten aus dem Buffer, unabhängig davon ob bereits alle Daten vom Sender empfangen wurden. Deshalb kann eine Übertragung über TCP auch folgendermaßen aussehen:

nonsynchsendrec

Die ursprüngliche Einzelnachricht des Clienten empfängt der Server vielleicht in mehreren Bruchstücken, die er aus dem TCP-Buffer liest. Aus diesem Grunde wird in dem Beispiel kontinuierlich innerhalb einer Schleife die Methode Receive aufgerufen, wobei die Methode solange blockiert bis genügend Daten im TCP-Buffer zur Verfügung stehen um den allokierten Puffer zu füllen. Da der Echo-Server alle eingehenden Daten einfach an den Clienten zurück sendet, muss er sich für Nachrichtengrenzen nicht interessieren, d.h. er muss keine Kenntnis von der Nachricht haben. Der Server liest in einer Schleife kontinuierlich den TCP-Buffer aus und sendet die empfangenen Daten einfach wieder direkt an den Clienten zurück. Als Abbruchbedingung dient die Methode Receive, die bei einem verbindungsorientierten Socket den Rückgabewert 0 liefert, wenn die Gegenseite den Socket schließt. Sind beim Aufruf von Reveive keine Daten im Buffer, blockiert die Methode solange, bis ein mit Socket.ReceiveTimeout gesetzter Timeout abgelaufen ist. Nach Ablauf dieser Zeitspanne löst Receive eine SocketException aus. Standardmäßig ist der Eigenschaft ReceiveTimeout der Wert 0 zugeordnet, d.h. die Methode Receive blockiert solange bis entweder Daten ausgelesen werden können oder die Gegenseite den Socket schließt.

TCP ist ein Stream (dt. Strom) und sollte auch als kontinuierlicher Datenstrom behandelt werden. Versuchen Sie nicht bei einem NetworkStream die Methode Flush aufzurufen, diese Methode hat keine Wirkung auf einen ungepufferten Netzwerkstrom. Der TCP/IP-Stack im Betriebssystem entscheidet wann und wie Pakete gesendet werden. Grundlage bildet der sogenannte Nagle-Algorithmus. Mit dem Nagle-Algorithmus wird das Versenden von vielen kleinen TCP-Datenpaketen über IP-Netze verhindert. Zu diesem Zweck werden beim Nagle-Mechanismus die kleinen Datenpakete zuerst zwischengespeichert und zu einem größeren Datenpaket zusammen gefasst. Mit dieser Technik soll das Netz von unnötig vielen kleinen Datenpaketen entlastet werden. In Verbindung mit dem Nagle-Algorithmus greift noch ein zweiter Algorithmus, der die Größe des Übertragungsfensters bei der TCP-Verbindung steuert. In der Regel versendet der TCP/IP-Stack ein Segment aus dem TCP-Buffer umgehend nach Ihrem Send-Befehl, doch dafür gibt es weder eine Garantie, noch können oder sollten Sie dieses Verhalten auf der Ebene erzwingen. Unter Windows bewirkt der Nagle-Algorithmus eine Zwischenspeicherung der Pakete am Socket für bis zu 200 Millisekunden. Es ist in .NET möglich die Winsock Option TCP_NODELAY zu setzen und damit den Nagle-Algorithmus zu deaktivieren. Dies wird mit der Eigenschaft Socket.NoDelay erreicht.

Es gibt Wege und Methoden Nachrichten die über TCP gesendet werden zu unterscheiden. Eine Möglichkeit ist immer eine fest definierte Nachrichtengröße zu transferieren. Eine weitere besteht darin jeweils immer die zugehörige Nachrichtengröße mit der Nachricht selbst zu übertragen. Und schlussendlich kann man das Protokoll so erweitern das ein eigenes Begrenzungssystem die Nachrichten voneinander eindeutig separiert. Doch das soll nicht Bestandteil dieses Tutorials sein und ist für uns auch nicht explizit relevant, solange wir wissen was sich im Hintergrund tatsächlich abspielt und unseren Code entsprechend anpassen können. Falls Sie an weiteren Details zu diesem Thema interessiert sind, können Sie einen Blick auf den Artikel http://www.codeplanet.eu/tutorials/csharp/66-client-server-modell.html werfen. Dort erfahren Sie im Kapitel Netzwerkprotokolle mehr über die Übertragung diskreter Nachrichten über das TCP.

Nun fehlt nur noch der Client der Daten an den Port des Servers sendet, so dass diese vom Server wieder zurück an den Clienten gesendet werden können. Ich überlasse die Programmierung des Clienten Ihnen und verweise auf die bisher bekannten Klassen und Methoden. Sollten Sie Probleme bei der Umsetzung haben, können Sie einen Blick in den von mir programmierten TCP-Clienten werfen. Dieser befindet sich unter den anderen Projekten im Anhang. Eine Kommunikation mit Ihrem Clienten und dem oben angegebenen Server könnte so aussehen:

Microsoft Windows XP [Version 5.1.2600]
(C) Copyright 1985-2001 Microsoft Corp.

C:\>TCPClientSocket.exe Hallo!
Connected to server... sending echo string
Sent 6 bytes to server...
Received 6 bytes from server: Hallo!
und
Handling client at 192.168.0.1:1984 - echoed 6 bytes.

HTTP-GET-Anforderung senden

Zu den alltäglichen Übertragungen über das Transmission Control Protocol im Internet gehört die HTTP-GET-Anforderung. Das HTTP ist ein Protokoll zur Übertragung von Daten über ein Netzwerk. Webbrowser nutzen das Protokoll, um Webseiten aus dem Internet zu laden. Dazu sendet der Browser eine dem HTTP entsprechend regelkonforme Anfrage an den Webserver. Der Webserver erwartet eine solche Anfrage in der Regel auf dem Port 80. Im folgenden Beispiel werden wir eine HTTP-GET 1.1 Anforderung an einen angegebenen Host senden. Diese einfache Anfrage beantwortet der Webserver indem er die Standardseite als HTML-Code zurückgibt. Üblicherweise ist das die Startseite der Homepage.

using System;
using System.Net;
using System.Text;
using System.Net.Sockets;
 
namespace CodePlanet.Articles.ProgrammingSockets
{
    /// <summary>
    /// Das folgende Kommandozeilenprogramm illustriert wie Sockets
    /// dazu verwendet werden können Daten zu empfangen und zu senden.
    /// </summary>
    public class HTTPGet
    {
        public static void Main(string[] args)
        {
            string host;
            int port = 80;
 
            if (args.Length == 0) {
                // Falls kein Hostname als Argument übergeben wurde soll
                // der lokale Host als Standard genommen werden.
                host = Dns.GetHostName();
            } else {
                host = args[0];
            }
 
            string result = SocketSendReceive(host, port);
            Console.WriteLine(result);
        }
 
        // Initialisiert die Socketverbindung und gibt diese zurück
        private static Socket ConnectSocket(string server, int port)
        {
            Socket sock = null;
            IPHostEntry hostEntry = null;
 
            hostEntry = Dns.GetHostEntry(server);
 
            // Nutze die Eigenschaft AddressFamily von IPEndPoint um Konflikte zwischen
            // IPv4 und IPv6zu vermeiden. Gehe dazu die Adressliste mit einer Schleife durch.
            foreach (IPAddress address in hostEntry.AddressList) {
                IPEndPoint ipo = new IPEndPoint(address, port);
                Socket tempSocket = new Socket(ipo.AddressFamily,
                                               SocketType.Stream,
                                               ProtocolType.Tcp);
 
                tempSocket.Connect(ipo);
 
                if (tempSocket.Connected) {
                    sock = tempSocket;
                    break;
                } else {
                    continue;
                }
            }
            return sock;
        }
 
        // Die Methode sendet eine HTTP GET 1.1 Anfrage an den Server und
        // empfängt die Daten
        private static string SocketSendReceive(string server, int port)
        {
            Socket sock = null;
 
            // Die zu sendenden Daten
            string request = "GET / HTTP/1.1\r\nHost: " + server +
                             "\r\nConnection: Close\r\n\r\n";
            // Kodiere den string in Bytes
            Byte[] bytesSent = Encoding.ASCII.GetBytes(request);
            // Lege ein Byte Array an für die zu emfangenden Daten
            Byte[] bytesReceived = new Byte[4096];
 
            // Instanziere ein gültiges Socket Objekt mit den übergebenen Argumenten
            sock = ConnectSocket(server, port);
 
            if (sock == null)
                return ("Connection failed!");
 
            // Sende den HTTP-Request
            sock.Send(bytesSent, bytesSent.Length, SocketFlags.None);
 
            int bytes = 0;
            string page = "Default HTML page on " + server + ":\r\n";
 
            // Empfange die Daten und konvertiere sie
            do {
                bytes = sock.Receive(bytesReceived, bytesReceived.Length, SocketFlags.None);
                // kovertiere die Byte Daten in einen string
                page = page + Encoding.ASCII.GetString(bytesReceived, 0, bytes);
            } while (bytes > 0);
 
            // Unterbinde alle weiteren Send() und Receive() Aktivitäten am Socket
            sock.Shutdown(SocketShutdown.Both);
            sock.Close();
 
            return page;
        }
    }
}

Die statische Methode ConnectSocket dient lediglich der Socketerstellung und Rückgabe. Je nachdem ob es sich um eine IPv4 oder IPv6 Adresse handelt wird die entsprechende Adressfamilie übergeben. In der zweiten Methode SocketSendReceive wird der übergebene Socket dazu verwendet eine HTTP-GET-Anforderung zu senden.

Neu in dem Quellcode ist die Klasse Encoding aus dem Namespace System.Text. Diese dient der Enkodierung von Zeichen. Da das Socket Objekt stets Sequenzen von Bytes sendet und empfängt, muss der string mit der HTTP-Get 1.1 Anfrage zunächst in eine Bytefolge konvertiert werden. Dazu wird die Methode GetBytes der Klasse Encoding aufgerufen. Die Methode ist mehrfach überladen:

public virtual byte[] GetBytes(char[]);
public virtual byte[] GetBytes(string);
public virtual byte[] GetBytes(char[], int, int);
public abstract int GetBytes(char[], int, int, byte[], int);
public virtual int GetBytes(string, int, int, byte[], int);

Die Klasse Encoding beinhaltet neben dem verwendeten Member ASCII, auch die Zeichensätze UTF8 und Unicode.

In einem späteren Kapitel werden Sie mehr über das HTTP und den Umgang mit diesem wichtigen Protokoll erfahren.



Zuletzt aktualisiert am Donnerstag, den 02. Januar 2014 um 23:03 Uhr
 
AUSWAHLMENÜ