Laden...

Pending mit Sockets

Erstellt von idontwantaname vor 16 Jahren Letzter Beitrag vor 16 Jahren 1.330 Views
I
idontwantaname Themenstarter:in
86 Beiträge seit 2006
vor 16 Jahren
Pending mit Sockets

Hallo!

Ich schreibe gerade eine Netzwerk-Anwendung und da ich lieber mit den Sockets anstatt TcpListener und TcpClient arbeite, möchte ich euch fragen, wie ich die Methode TcpListener.Pending() realisieren könnte, da ich sie äußerst praktisch finde.

Ich möchte nicht auf den TcpListener umsteigen, ebenso interessiert mich die Frage auch ohne konkretes Problem 😉

Habt ihr Ideen?

Lg oli

F
35 Beiträge seit 2008
vor 16 Jahren

Hallo oli!

Pending mit Sockets ist einfach:

Socket.Accept() wartet solange, bis ein Client connecten möchte.

Du brauchst also:

while (true) { (das ist hier kein 99% Überlauf 😉)
Socket mySock = Socket.Accept()
}

Das Problem, was an diesem Code auftritt, ist allerdings ein Multithreading Thema.

Daher musst du eine Klasse erstellen, welcher du anschließend das Socket übergibst,
und die dann einen weiteren while-loop besitzt, der für das Empfangen zuständig ist.

Du hast somit eine while schleife in einem Thread, der nur die ankommenden Verbindungen handled, und anschließend für jedes akzeptierte Socket eine
neue Klasseninstanz, die für das Senden und Empfangen zuständig ist.

Dieser klasse musst du allerdings eine ID übergeben, damit du hinterher die
Sockets auseinanderhalten kannst (das kommt allerdings auf den Verwendungszweck an).
Mit der ID kannst du dann die Sockets auch aus der Hashtable holen, falls du weitere
Operationen durchführen möchtest (außer senden und Empfangen).

Der TcpListener macht übrigens nichts anderes als das!
Darum kannst du ruhig den Listener verwenden, und anschließend
TcpListener.AcceptSocket verwenden. So hast du dann auch Zugriff auf die
komplette Socket Schnittstelle.

Wie du es machst, bleibt dir überlassen 🙂

Mit freundlichem Gruß

Fabian Stern

info@smart-coding.com
www.smart-coding.com

I
idontwantaname Themenstarter:in
86 Beiträge seit 2006
vor 16 Jahren

Mir ist schon klar, dass Socket.Accept() eine blockierende Methode ist und ich einen extra Thread dafür verwenden sollte (bzw. muss) und das tue ich auch.

Was ich jedoch erreichen möchte:

while (active)
{
    if (pending)
    {
        Socket client = socket.Accept();
    }
    else
    {
        Thread.Sleep(sleepTime);
    }
}
socket.Close();

damit ich durch setzen der Variable active auf false den Vorgang sanft beenden kann und keine ThreadAbortException auslösen muss.

Inzwischen habe ich aber folgende Lösung bzw. Workaround:


private bool accept(Socket server, out Socket client)
{
    try
    {
        server.Blocking = false; // nur einmal aufgerufen woanders im Code
        client = server.Accept();
        return true;
    }
    catch (SocketException e)
    {
        if (e.ErrorCode == 10035) // Fehlercode, wenn Ressource gerade nicht vorhanden
        {
            client = null;
            return false;
        }

        throw e;
    }
}

while (active)
{
    Socket client;
    if (accept(socket, out client))
    {
        // mache was anderes
    }
    else
    {
        Thread.Sleep(sleepTime);
    }
}

Lg oli

PS: suche aber immernoch nach einem eleganteren Weg 😉
PPS: Codesegmente sind nur hier im Forum geschrieben weil ich grad nicht zu Hause bin, könnten also fehlerhaft sein!

F
35 Beiträge seit 2008
vor 16 Jahren

Hallo,

ich verstehe in deinem Fall nicht, was du eigentlich erreichen möchtest.
Das mag vielleicht an mir liegen, aber es könnte auch an dem Segment hapern.

Also: Was brauchst du genau ?

Wenn es dir nur um das saubere Beenden deiner Socketschlange geht,
dann mach es wie ich vorgeschlagen habe in einer separaten Klasse,
nutze

Socket.Poll(-1,CanRead) wie CanWrite, wenn nicht, Dispose.
Wenn du nämlich eine Hashtable hast, kannst du sowas machen:

myOwnSocketClass clsOwn = (myOwnSocketClass)myhash[id];
clsOwn.DoClose(); (selbsterstellt)
clsOwn.Dispose(); (selbsterstellt)
myhash[id] = null;

Und so beendet sich der Thread selbst, denn er hat nichts mehr zu tun.

Deine activevariable kann dabei so bleiben.
Ein else zum Pending-Abfangen ist allerdings völlig unnütz.
Vielmehr musst du während du Pending machst, prüfen, ob dann auch active auf false ist.
Wenn ja, rufst du nicht Accept auf, sondern Disposed deine SocketKlasse.

Mit freundlichem Gruß

Fabian Stern

info@smart-coding.com
www.smart-coding.com