Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Netzwerke (https://www.delphipraxis.net/14-netzwerke/)
-   -   Delphi Sockets verwalten (WSAAsyncSelect vs WSAEventSelect) (https://www.delphipraxis.net/117519-sockets-verwalten-wsaasyncselect-vs-wsaeventselect.html)

Mr_G 19. Jul 2008 17:54


Sockets verwalten (WSAAsyncSelect vs WSAEventSelect)
 
Hallo zusammen...
Nachdem ich mir ein Tutorial zu Socketprogrammierung mittels WinAPI angesehen habe wollte ich das auch mal in mein Projekt einbauen. Mein Problem ist dabei das ich nicht weiß wie ich die Sockets beim Empfangen verwalten soll wenn ich mit TCP arbeite.

Möglichkeit 1:
Ich arbeite mit WSAAsyncSelect und übergebe ein Fensterhandle, das eine Message bekommt, die über das enstpechende Ereignis informiert, und gleich das Sockethandle mitliefert. Problem: Ich habe kein Fenster und ich weiß nicht ob so eine Lösung tragbar ist, bei der man einfach ein unsichtbares Fenster erzeugt.

Möglichkeit 2:
Ich arbeite mit Events und setze für jedes Socket ein Event woraufhin ich mit WSAWaitForMultipleEvents darauf warte das eines ausgelöst wird. Das Problem, das ich hier sehe: Ich kenne nur das auslösende Event und nicht das Sockethandle... ich müsste mir also ne Liste basteln und bei jedem Event nach dem Socket suchen :shock: ... das kanns ja auch nicht sein.

Möglichkeit 3:
Ich erzeuge für jedes Socket einen Thread der einfach wartet. Probleme könnten hier Overhead und Sychronisation sein.

So... und nun die große Frage: Wie macht man es richtig?

Apollonius 19. Jul 2008 20:36

Re: Sockets verwalten (WSAAsyncSelect vs WSAEventSelect)
 
Wenn du sowieso eine Nachrichtenschleife hast, würde ich WSAAsyncSelect verwenden.

Mr_G 19. Jul 2008 21:16

Re: Sockets verwalten (WSAAsyncSelect vs WSAEventSelect)
 
Zitat:

Zitat von Apollonius
Wenn du sowieso eine Nachrichtenschleife hast, würde ich WSAAsyncSelect verwenden.

Die habe ich aber leider nicht. Da es sich um einen Service handelt weiß ich auch nicht ob ich so einfach ein unsichtbares Fenster erzeugen kann/will.

Apollonius 19. Jul 2008 22:59

Re: Sockets verwalten (WSAAsyncSelect vs WSAEventSelect)
 
Ich vermute mal, dass der Service handgestrickt ist, also ohne VCL. Dann würde ich WSAEventSelect nehmen.
Aus dem Event den Socket zu finden, ist kein Problem. Du speicherst in einer Liste die Sockets und die Event-Handles. WSAWaitForMultipleEvents gibt bei Erfolg den Index des Events, und damit des Sockets, zurück.
Du könntest aber auch ein globales Event statt einem pro Socket verwenden. Wenn das Event signalisiert wird, kannst du mit der Funktion Select herausfinden, in welche Sockets du schreiben kannst und bei welchen Daten anliegen. Oder du rufst zu jedem Socket WSAEnumNetworkEvents auf. Du würdest damit viele Events sparen, was in jedem Fall zu begrüßen ist. Threads kannst du dir eigentlich nur leisten, wenn du wenige Sockets hast. Threads benötigen eine ganze Menge Ressourcen.

Mr_G 19. Jul 2008 23:56

Re: Sockets verwalten (WSAAsyncSelect vs WSAEventSelect)
 
Danke erstmal für die ganzen neuen Denkanstöße!
Zitat:

Zitat von Apollonius
Ich vermute mal, dass der Service handgestrickt ist, also ohne VCL.

Stimmt...
Zitat:

Zitat von Apollonius
Dann würde ich WSAEventSelect nehmen.
Aus dem Event den Socket zu finden, ist kein Problem. Du speicherst in einer Liste die Sockets und die Event-Handles. WSAWaitForMultipleEvents gibt bei Erfolg den Index des Events, und damit des Sockets, zurück.

Das war ja die Möglichkeit 2, die ich angegeben hab. Mir stellt sich die Frage ob das nicht viel zu aufwendig ist bei jedem auslösen des Events die Liste zu durchsuchen.
Zitat:

Zitat von Apollonius
Du könntest aber auch ein globales Event statt einem pro Socket verwenden. Wenn das Event signalisiert wird, kannst du mit der Funktion Select herausfinden, in welche Sockets du schreiben kannst und bei welchen Daten anliegen.

Die Funktion sieht interessant aus aber ich verstehe leider nicht wie ich mit FD_SET umgehen muss. In der WinSock Unit handelt es sich bei FD_SET um eine procedure die ein Socket übergeben bekommt. Ist damit das Listenersocket gemeint von dem alle weiteren Verbindungen das Event geerbt haben :?:
Zitat:

Zitat von Apollonius
Oder du rufst zu jedem Socket WSAEnumNetworkEvents auf. Du würdest damit viele Events sparen, was in jedem Fall zu begrüßen ist.

Das hört sich irgendwie nicht so gut an... ich habe mir dazu mal das passende Beispiel in der MSDN angesehen und so wie ich das verstehe würde sich das bei vielen Verbindungen auch schwer tun. Ich hab das ganze nämlich so vestanden, dass dabei auch für jedes Socket ein Event erzeugt wird und anschließend alle Sockets durchlaufen werden. Dabei wird bei jedem Socket 1 Sekunde auf das entsprechende Event gewartet und wenn etwas signalisiert wurde, wird WSAEnumNetworkEvents genutzt um herauszufinden was alles seit dem letzten Aufruf passiert ist. Ich kann mich um die Uhrzeit auch schon völlig verschätzen aber für mich würde das bedeuten, das z.B. im Falle von 30 Verbindungen, bei denen Verbindung 30 Daten überträgt, im schlechtesten Falle erst für jede Verbindug davor gewartet wird (29 Sekunden lang !?) und dann evtl. aufgetretene Events bei Verbindung 30 bearbeitet werden.
Zitat:

Zitat von Apollonius
Threads kannst du dir eigentlich nur leisten, wenn du wenige Sockets hast. Threads benötigen eine ganze Menge Ressourcen.

Ich hab mich auch da schonmal umgesehen gehabt und meine da sowas wie WorkerThreads bzw. einen Threadpool gefunden zu haben. Ich glaube es war in dem Tutorial von Luckie. Leider weiß ich auch dabei nicht ob es sich um eine echte Alternative handelt.
Ich wäre für jeden Fingerzeig dankbar!
Gruß

Mr_G

Zacherl 20. Jul 2008 10:05

Re: Sockets verwalten (WSAAsyncSelect vs WSAEventSelect)
 
Hey, mich würde mal das Socket Tutorial interessieren :) Wollte nämlich mal eine eigene TClientSocket / TServerSocket Klasse basteln.

Apollonius 20. Jul 2008 10:47

Re: Sockets verwalten (WSAAsyncSelect vs WSAEventSelect)
 
Zitat:

Zitat von Mr_G
Mir stellt sich die Frage ob das nicht viel zu aufwendig ist bei jedem auslösen des Events die Liste zu durchsuchen.

Du durchsuchst die Liste nicht! WSAWaitForMultipleEvents gibt dir den Array-Index des Events zurück.
Zitat:

Zitat von Mr_G
Die Funktion sieht interessant aus aber ich verstehe leider nicht wie ich mit FD_SET umgehen muss. In der WinSock Unit handelt es sich bei FD_SET um eine procedure die ein Socket übergeben bekommt.

Das ist zumindest in meiner Unit WinSock ausführlich dokumentiert: Es gibt einen Record TFD_SET und eine Routine (eine Art Konstruktor) FD_SET. Wegen des Namenskonflikts gibt es keinen Typen FD_SET, du musst TFD_SET verwenden.
Zitat:

Zitat von Mr_G
Das hört sich irgendwie nicht so gut an... ich habe mir dazu mal das passende Beispiel in der MSDN angesehen und so wie ich das verstehe würde sich das bei vielen Verbindungen auch schwer tun. Ich hab das ganze nämlich so vestanden, dass dabei auch für jedes Socket ein Event erzeugt wird und anschließend alle Sockets durchlaufen werden. Dabei wird bei jedem Socket 1 Sekunde auf das entsprechende Event gewartet und wenn etwas signalisiert wurde, wird WSAEnumNetworkEvents genutzt um herauszufinden was alles seit dem letzten Aufruf passiert ist. Ich kann mich um die Uhrzeit auch schon völlig verschätzen aber für mich würde das bedeuten, das z.B. im Falle von 30 Verbindungen, bei denen Verbindung 30 Daten überträgt, im schlechtesten Falle erst für jede Verbindug davor gewartet wird (29 Sekunden lang !?) und dann evtl. aufgetretene Events bei Verbindung 30 bearbeitet werden.

Das hast du falsch verstanden. Die Idee ist: Entweder du verwendest für jeden Socket ein Event (schnell, aber etwas resourcenintensiver) oder ein Event für alle Sockets. Bei letzterer Möglichkeit weißt du allerdings nicht, welcher Socket etwas von dir will. Dazu verwendest du WSAEnumNetworkEvents.
Zitat:

Zitat von Mr_G
Ich hab mich auch da (Threads) schonmal umgesehen gehabt und meine da sowas wie WorkerThreads bzw. einen Threadpool gefunden zu haben. Ich glaube es war in dem Tutorial von Luckie. Leider weiß ich auch dabei nicht ob es sich um eine echte Alternative handelt.

Du kannst hier nicht direkt einen Threadpool verwenden, denn du bräuchtest für jeden Socket einen eigenen Thread. Das ist aber eine Zumutung für das System, wenn du viele Sockets hast.

Mr_G 20. Jul 2008 11:44

Re: Sockets verwalten (WSAAsyncSelect vs WSAEventSelect)
 
Danke für die ausdauernde Hilfe!
Zitat:

Zitat von Apollonius
Du durchsuchst die Liste nicht! WSAWaitForMultipleEvents gibt dir den Array-Index des Events zurück.

Ich galube ich habe da Tomaten auf den Augen... ich hab doch dann zwar das Eventhandle... aber das muss ich doch noch einem Sockethandle zuordnen, oder?
Zitat:

Zitat von Apollonius
Das ist zumindest in meiner Unit WinSock ausführlich dokumentiert: Es gibt einen Record TFD_SET und eine Routine (eine Art Konstruktor) FD_SET. Wegen des Namenskonflikts gibt es keinen Typen FD_SET, du musst TFD_SET verwenden.

War gestern schon ein bisschen spät... nun habe ich es verstanden... vielen Dank!
Zitat:

Zitat von Apollonius
Das hast du falsch verstanden. Die Idee ist: Entweder du verwendest für jeden Socket ein Event (schnell, aber etwas resourcenintensiver) oder ein Event für alle Sockets. Bei letzterer Möglichkeit weißt du allerdings nicht, welcher Socket etwas von dir will. Dazu verwendest du WSAEnumNetworkEvents.

Das wäre zwar eine Möglichkeit, aber select würde mir doch dann das gleiche bringen und wäre einer Schleife mit WSAEnumNetworkEvents vorzuziehen, oder?
Zitat:

Zitat von Apollonius
Du kannst hier nicht direkt einen Threadpool verwenden, denn du bräuchtest für jeden Socket einen eigenen Thread. Das ist aber eine Zumutung für das System, wenn du viele Sockets hast.

Ok! Threads sind abgehakt :mrgreen:

Zitat:

Zitat von Zacherl
Hey, mich würde mal das Socket Tutorial interessieren :) Wollte nämlich mal eine eigene TClientSocket / TServerSocket Klasse basteln.

Also das API-Tutorial hab ich verlinkt:
Zitat:

Zitat von Mr_G
...Nachdem ich mir ein Tutorial zu Socketprogrammierung mittels WinAPI angesehen habe ...


Apollonius 20. Jul 2008 11:51

Re: Sockets verwalten (WSAAsyncSelect vs WSAEventSelect)
 
WSAWaitForMultipleEvents gibt dir nicht das auslösende Event-Handle zurück, sondern den Index. Wenn du also zwei Listen hast, in der einen die Events, in der anderen die Sockets, kannst du die erste an WSAWaitForMultipleEvents übergeben, welches dir den Index des signalisierten Events zurückgibt. Diesen Index kannst du nun verwenden, um mit der zweiten Liste den Socket anzusprechen.

Bezüglich WSAEnumNetworkEvents hast du grundsätzlich Recht, aber Select sagt dir nichts zu FD_CLOSE, FD_ACCEPT und einigen anderen Ereignissen.

Mr_G 20. Jul 2008 13:28

Re: Sockets verwalten (WSAAsyncSelect vs WSAEventSelect)
 
Zitat:

Zitat von Apollonius
WSAWaitForMultipleEvents gibt dir nicht das auslösende Event-Handle zurück, sondern den Index. Wenn du also zwei Listen hast, in der einen die Events, in der anderen die Sockets, kannst du die erste an WSAWaitForMultipleEvents übergeben, welches dir den Index des signalisierten Events zurückgibt. Diesen Index kannst du nun verwenden, um mit der zweiten Liste den Socket anzusprechen.

Das ist ja eine simple Lösung :wall: Im MSDN Beispiel ist es ganz ähnlich. Das ganze wurde aber noch mit WSAGetOverlappedResult verknüpft... leider versteh ich da den Sinn nicht. Brauch ich das auch?
Zitat:

Zitat von Apollonius
Bezüglich WSAEnumNetworkEvents hast du grundsätzlich Recht, aber Select sagt dir nichts zu FD_CLOSE, FD_ACCEPT und einigen anderen Ereignissen.

Auf ein Accept könnte man doch schließen wenn man gerade mit dem Listen-Socket arbeitet und bei einem Close liefert recv laut MSDN den Fehler WSAECONNRESET. Evtl. könnte man ja auch nochmal WSAEnumNetworkEvents für das entsprechnede Socket aufrufen... dann spart man sich auch die Schleife.

So wie ich das nun sehe haben sich da zwei Ansätze rauskistallisiert (Danke dafür erstmal!). Ist eine der Lösungen der anderen aus bestimmten Gründen vorzuziehen?


Alle Zeitangaben in WEZ +1. Es ist jetzt 19:58 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz