Autor Beitrag
C#
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 561
Erhaltene Danke: 65

Windows 10, Kubuntu, Android
Visual Studio 2017, C#, C++/CLI, C++/CX, C++, F#, R, Python
BeitragVerfasst: Fr 10.02.12 01:31 
Hey @ll,

ich dachte wenn ich mich sowieso gerade damit rumschlage, setzte ich hier mal n kleines Tut rein zum Thema Asynchrones und Synchrones verbinden mit TcpListener.

Synchrones Verfahren:
ausblenden volle Höhe C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
namespace Tutorial
{
    using System;
    using System.Net;
    using System.Net.Sockets;

    private Class TcpTutorial
    {
        static void Main()
        {
            TcpClient myClient = AcceptTcpClient(12000);
            //...
        }

        private TcpClient AcceptTcpClient(int port)
        {
//Zuerst eine neue Instanz der TcpListener Klasse erzeugen. Mit der port-Variable geben wir den Port an, der später abgehört werden soll.
            TcpListener listener = new TcpListener(IPAddress.Any, port); 

//Den TcpListener starten. Ab diesem Zeitpunkt hört er den Port ab.
            listener.Start(); 

//Hier erstellen wir eine neue Instanz des TcpClients und nehmen gleich eine ausstehnde Verbindung an. 
//Ist keine ausstehnde Verbindung vorhanden, wird an dieser Stelle solange gewartet, bis eine Verbindungsanfrage eingeht.
            TcpClient client = listener.AcceptTcpClient(); 

//Hier müssen wir dem TcpListener natürlich auch wieder mitteilen, dass er das abhören beenden kann.
            listener.Stop(); 

//Zum Schluss wird der TcpClient, der nun an seinen Gegenüber gebunden ist,noch zum Aufrufer weitergegeben.
            return client; 
        }
    }
}

Wie ihr seht ist die synchrone Methode ganz einfach zu realisieren.
Die Portnummer hier ist einfach Zufall. Die Ports und ihre Funktion könnt ihr hier nachschlagen: www.iana.org

Nun zum etwas komplizierteren Teil:

Asynchrones Verfahren:
Zuerst einmal stellt sich die Frage warum man das ganze überhaupt asynchron abwickeln soll.
Aus einem ganz einfachen Grund: Wenn wir nicht auf einen Clienten warten müssen, oder unsere WindowsForm noch nebenher laufen soll, müssen wir auf die Asynchrone Variante zurückgreifen, da sonst die AcceptTcpClient()-Metode unser komplettes Programm - oder zumindest den Hauptthread - blockiert.
ausblenden volle Höhe C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
namespace Tutorial
{
    using System;
    using System.Net;
    using System.Net.Sockets;

    private Class TcpTutorial
    {
        private TcpClient myClient;

        static void Main()
        {
            StartAsyncAccepting(12000);
            //...
        }

        private void StartAsyncAccepting(int port)
        {
            TcpListener listener = new TcpListener(IPAddress.Any, port);
            listener.Start();
            listener.BeginAcceptTcpClient(AsyncAcceptingCallback, listener);
        }

        private void ListenerAcceptingCallback(IAsyncResult state)
        {
            TcpListener listener = (TcpListener)state.AsyncState; //Typecast
            TcpClient client = listener.EndAcceptTcpClient(state);
            listener.Stop();
            myClient = client;
        }
    }
}

Nun zur Erklärung:
TcpListener.BeginnAcceptTcpClient(AsyncCallback callback, IAsyncResult result) Bei diesem Aufruf startet ein neuer Hintergrundthread mit der Instanz des aktuellen TcpListeners (hier: listener) und wartet auf einen eingehenden Verbindungsversuch.
Das AsyncCallback ist unsere Methode, die aufgerufen wird sobald eine Anfrage da ist und IAsyncResult ist ein Objekt, das Informationen zum aktuellen Verbindungsversuch beinhaltet. Im Klartext: die Instanz unseres TcpListeners.

So. Wenn jetzt eine Verbindungsanfrage ankommt, wird unsere Callback-Methode ausgelöst (hier: ListenerAcceptingCallback).
Das IAsyncResult in der Parameterliste ist zwingend notwendig, da hier die Instanz des TcpListeners übergeben wird. Außerdem akzeptiert BeginAcceptTcpClient() nur diese Form.

Wie ich oben schon gesagt habe, beinhaltet das IAsyncResult state die TcpListener-Instanz, die wir in der StartAsyncAccepting()-Methode benutzt haben. Jetzt müssen wir nur einen weiteren TcpListener definieren und die Instanz per Typecast übergeben.
In der zweiten Zeile dieser Methode wird eine neue TcpClient-Instanz erzeugt, welche mittels EndAcceptTcpClient() initialisiert wird.
Die EndAcceptTcpClient(state)-Methode nimmt dann die ausstehnde Verbindung an.
Wichtig: der TcpListener darf erst jetzt gestoppt werden und nicht in StartAsyncAccepting oder vor EndAcceptTcpClient().

Und da alles in dem Hintergrundthread läuft (auch die Callback-Methode) blockiert unsere Form nicht und das Programm läuft ungestört weiter.

Ich hoffe das Tutorial ist hilfreich.
TcpClient folgt wenn ich ausgeschlafen bin ;).

Rechtschreibfehler sind geistiges Eigentum, aber ich beanspruche keine Urheberrechte daran ;).

_________________
Der längste Typ-Name im .NET-Framework ist: ListViewVirtualItemsSelectionRangeChangedEventHandler