Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

WinSock2 + blockierendes recv + CreateThread + (C++ / WinAPI)

29 views
Skip to first unread message

Robert Hartmann

unread,
Apr 22, 2013, 6:12:40 PM4/22/13
to
Hallo zusammen,

Ich bastel immernoch an meiner "AdapterSoftware"
(vgl. Posting "NamedPipe + Zugriffsrechte + CreateProcessAsUser"
mit Message-ID: <kj2iv4$tjd$1...@speranza.aioe.org> ).


Prinzipiell bin ich schon fast zufrieden.

An einer Stelle ruft meine Software in blockierender Weise recv auf
einem Socket auf.

Falls der Client noch verbunden ist, aber einfach nichts schickt ist das
blockierende empfangen genau das was ich möchte.

Fällt der Client aber nun weg, oder kommt es zu sonstiger Störung der
Verbindung, dann wartet der recv eben weiterhin.

Ich würde gerne vor dem recv einen neuen Thread starten,
in dem überprüft wird, ob überhaupt noch ein Client mit dem Socket
verbunden ist. und falls keine Verbindung mehr da ist, muss
das recv abgebrochen werden.

Oder sollte ich es anders herum machen:

Das blockierende recv in einen extra Thread auslagern und
im normalen Programmfluss eine Schleife schreiben, in der eine gewisse
Zeitspanne gewartet wird bevor ein Zustandstest gemacht wird.
sollte die schleife verlassen werden, weil der Test schief ging, dann
könnte der Thread gezwungen werden sich zu beenden und somit das recv
abzubrechen. sollte der Thread beendet werden nach erfolgreichem recv,
dann könnte die schleife ebenfalls beendet werden...

Was hört sich gescheiter an?

Gruß Robert



Ulrich Eckhardt

unread,
Apr 23, 2013, 3:29:25 AM4/23/13
to
Am 23.04.2013 00:12, schrieb Robert Hartmann:
> An einer Stelle ruft meine Software in blockierender Weise recv auf
> einem Socket auf.
>
> Falls der Client noch verbunden ist, aber einfach nichts schickt ist das
> blockierende empfangen genau das was ich möchte.
>
> Fällt der Client aber nun weg, oder kommt es zu sonstiger Störung der
> Verbindung, dann wartet der recv eben weiterhin.

Naja, der Timeout beim Ziehen des Steckers ist bei TCP recht lang. Wenn
die TCP-Verbindung aber offiziell abgebaut ist, dann sollte recv()
SOCKET_ERROR zurueckgeben. Hast Du mal versucht den "TCP keepalive
timeout" herunterzusetzen um einen gezogenen Stecker schneller zu
detektieren? Ich hab' es selber noch nicht ausprobiert, aber der Doku
nach sollte das genau das Mittel der Wahl sein.


> Ich würde gerne vor dem recv einen neuen Thread starten,
> in dem überprüft wird, ob überhaupt noch ein Client mit dem Socket
> verbunden ist. und falls keine Verbindung mehr da ist, muss
> das recv abgebrochen werden.

Wie willst Du pruefen ob der Client noch da ist? Wenn Du nicht einen
zweiten Kanal zum Client hast, dann sehe ich nur die Methode dem
TCP-Stack zu vertrauen, also recv() einfach aufzurufen und zu warten. Du
kannst uebrigens auch ein Event mit dem Socket verbinden, dann kannst Du
mit WaitForMultipleObjects() arbeiten. Das erlaubt es Dir einen Timeout
zu definieren oder ein zweites Event zum manuellen Abbruch zu setzen.
Ich glaube der Ansatz mit dem zweiten Thread und den damit verbundenen
Problemen kannst Du vermeiden.

Viel Erfolg!

Uli



Robert Hartmann

unread,
Apr 23, 2013, 5:12:50 PM4/23/13
to
Hallo,

Am 23.04.2013 09:29, schrieb Ulrich Eckhardt:
[...]

>
> Wie willst Du pruefen ob der Client noch da ist?

Du bist gut, danke :-)
Das war die richtige Frage.

Annahme:
Dass eine existierende localhost-socket-verbindung einfach abreißt, ohne
dass einer der beiden beteiligten Prozesse verschwindet, halte ich fast
für unmöglich.


Die Situation:

Windows-PC1:
ServiceAnwendung <=socket localhost=> ServerProxy
/SocketServer /SocketClient

<==NamedPipe (wegen Zugriffsrechten) ==>
Windows-PC2:
ClientAnwendung <=socket localhost=> ClientProxy
/SocketClient /SocketServer


ServerProxy startet ServiceAnwendung, d.h. ServerProxy kennt
ProcessInformation von ServiceAnwendung.

ServerProxy könnte parallel zum recv (warten auf Antwort von
ServiceAnwendung) testen, ob der Prozess noch da ist, wenn der
Prozess nicht mehr da ist, müsste recv abgebrochen werden.


ClientProxy startet ClientAnwendung, kennt ProcessInformation, und
könnte parallel zum blockierenden recv schauen, ob ClientAnwendung
noch als Process existiert. Wenn der Prozess nicht mehr da ist, müsste
recv abgebrochen werden.



> Wenn Du nicht einen
> zweiten Kanal zum Client hast, dann sehe ich nur die Methode dem
> TCP-Stack zu vertrauen, also recv() einfach aufzurufen und zu warten. Du
> kannst uebrigens auch ein Event mit dem Socket verbinden, dann kannst Du

Socket mit Event verbinden, geht das ohne .NET und MFC?
Geht das _nur_ mit WinAPI bzw WinSock2?

> mit WaitForMultipleObjects() arbeiten.

Du meinst wahrscheinlich WSAWaitForMultipleEvents(), oder?

>Das erlaubt es Dir einen Timeout
>zu definieren oder ein zweites Event zum manuellen Abbruch zu setzen.

Werde ich mir mal genauer ansehen.


> Ich glaube der Ansatz mit dem zweiten Thread und den damit verbundenen
> Problemen kannst Du vermeiden.

Wäre besser und übersichtlicher :-)

>
> Viel Erfolg!

Danke,
Gruß Robert

Ulrich Eckhardt

unread,
Apr 24, 2013, 2:21:18 AM4/24/13
to
Am 23.04.2013 23:12, schrieb Robert Hartmann:
> Annahme:
> Dass eine existierende localhost-socket-verbindung einfach abreißt, ohne
> dass einer der beiden beteiligten Prozesse verschwindet, halte ich fast
> für unmöglich.
[...]
> ServerProxy könnte parallel zum recv (warten auf Antwort von
> ServiceAnwendung) testen, ob der Prozess noch da ist, wenn der
> Prozess nicht mehr da ist, müsste recv abgebrochen werden.

Wenn der Prozess nicht mehr da ist, dann hat das OS den Socket
geschlossen, alles andere waere ein Bug im TCP-Stack. Das recv() auf der
anderen Seite gibt dann ein -1 zurueck und WSAGetLastError() einen
entsprechenden Fehlercode. Nur zur Info: Wenn die andere Seite
shutdown() aufruft gibt recv() eine Null zurueck, aber auch das
bedeutete dass die Verbindung geschlossen ist.



> Socket mit Event verbinden, geht das ohne .NET und MFC?
> Geht das _nur_ mit WinAPI bzw WinSock2?

Ja!


>> mit WaitForMultipleObjects() arbeiten.
>
> Du meinst wahrscheinlich WSAWaitForMultipleEvents(), oder?

Also formell ist das natuerlich die Richtige Variante(tm). Ich habe mich
aber bisher nicht um die Unterschiede zwischen WinSock-Events und
win32-Events geschert und bin dabei auch nicht auf die Schnauze
gefallen. Vielleicht ist das aber nur Glueck.

Ansonsten, guck' Dir mal WSAEventSelect() und WSAEnumNetworkEvents() an.
Wenn Du bloss einen Timeout brauchst, dann kannst Du natuerlich auch
noch select() benutzen.

Uli

0 new messages