ERLEDIGT
JA
JA
ANTWORTEN
4
4
ZUGRIFFE
824
824
EMPFEHLEN
-
22.06.10 16:59 #1
- Registriert seit
- Oct 2003
- Beiträge
- 114
Hi Forum
Ich habe einen .NET Windows Service der auf einem Socket horcht:
Code :1 2 3 4 5 6 7 8 9 10 11 12
Dim smtpPort as Integer = 2525 Dim ipHostInfo As IPHostEntry = Dns.GetHostEntry(Dns.GetHostName()) Dim localEndPoint As New IPEndPoint(ipHostInfo.AddressList(0), smtpPort) Dim listener As New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp) listener.Bind(localEndPoint) listener.Listen(10) 'blockierend Dim socket As Socket = listener.Accept()
So das funktioniert bis jetzt eigentlich sauber (try-catch etc. weggelassen). Wenn ich nun meinen Service über die MMC restarte, dann erhalte ich Fehlermeldungen betreffend:
Also dachte ich mir, schliesse ich den Socket im Service-OnStop()-Event so etwas à la:Normalerweise darf jede Socketadresse (Protokoll, Netzwerkadresse oder Anschluss) nur jeweils einmal verwendet werden
Doch damit erhalte ich nun eine Exception bei listener.accept():Code :1 2
'listener.Disconnect(False) listener.Close()
Wie schliesse ich denn nun den Socket richtig? Wenn ich den Service nur Stoppe, 2,3 Sekunden warte und dann wieder starte, dann funktioniert es ohne Fehlemeldungen. Einfach der Restart hat er nicht so gerne. Daher möchte ich eben die accept() unterbrechen. Wie geht das nach Kochbuch?System.Net.Sockets.SocketException: Ein Blockierungsvorgang wurde durch einen Aufruf von WSACancelBlockingCall unterbrochen
bei System.Net.Sockets.Socket.Accept()
cheerioh & thx
SiS
-
Ich denke das passt schon so. Mit dem Disconnect-Aufruf zwingst du die Accept-Methode, dass sie zurückkehrt. Da sie aber keinen Rückgabewert definieren kann, wirft sie eine Fehlermeldung.
Eine SocketException kann aber auch andere Ursachen haben; um diese herauszufinden liefert dir die ErrorCode-Eigenschaft der SocketException genauere Informationen. Informationen zum ErrorCode findest du hier. Also wenn bei dir der Wert WSAEINTR=10004 im ErrorCode drin steht, dann kannst du die Fehlermeldung einfach ignorieren bzw. weißt, dass ein anderer Thread die Disconnect-Methode (oder Ähnliche) aufgerufen hat.
P.S.: Bitte nimm das nicht 100%-ig für wahre Münze, habe nur MSDN gelesen, aber keine Erfahrung damit.Geändert von Shakie (23.06.10 um 19:54 Uhr)
-
25.06.10 10:26 #3
- Registriert seit
- Oct 2003
- Beiträge
- 114
Hi Shakie
Danke für Deine Links. Wie es scheint lässt sich das Problem genau so "umgehen".
Code :1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
Try listener.Bind(localEndPoint) listener.Listen(10) ' Start listening for connections. running = True While running ' zzzzzzzzzzz.... Dim socket As Socket = listener.Accept() Dim session As New SMTPSession(socket) ' do session stuff End While 'ready for next message Catch e As Exception If System.Runtime.InteropServices.Marshal.GetLastWin32Error() = 10004 Then ' ignore error of blocking operation WSACancelBlockingCall Else ' do error handler stuff End If End Try
cheerioh
SiSGeändert von StehtimSchilf (25.06.10 um 10:29 Uhr)
-
Ich würde die Fehlerbehandlung so gestalten:
Das erscheint mir hübscher als der Aufruf von Marshal.GetLastWin32Error. Und ich vermute der Zugriff auf die ErrorCode-Eigenschaft sollte schneller sein als der Aufruf von Marshal.GetLastWin32Error.Code vbnet:1 2 3 4 5 6 7 8 9
Try ' ... Catch ex As Net.Sockets.SocketException If ex.ErrorCode <> 10004 Then ' Fehlerbedhanlung für SocketExceptions End If Catch ex As Exception ' Fehlerbedhanlung für andere Exceptions End Try
-
GetLastWin32Error dürfte kaum mehr Aufwand sein, aber möglicherweise nicht funktionieren. Der CLR-Host selbst ruft ja ständig Windows-Funktionen auf (schon alleine zwischen accept und dem Abfangen der Exception wohl einige), welche wiederum fs:[0x34] (Last Error Code) verändern. Deshalb macht ja auch Marshal.GetLastWin32Error auch nicht das, was GetLastError im unverwalteten macht
Code asm:1 2 3 4
_GetLastError@0: mov eax,dword ptr fs:[00000018h] mov eax,dword ptr [eax+34h] ret
sondern es wird eine Variable abgefragt, welche für jeden Thread den letzten von aussen aufgerufenen Errorcode enthält. Das funktioniert jedoch nur, wenn die Funktion, von welcher du den Errorcode wissen möchtest auch das Attribut SetLastError(true) hat. Nur dann speichert der CLR-Host den Code der Funktion. Bedenkt man nun, dass ErrorCode ein Property ist, so ist beides nur ein simpler Funktionsaufruf, welcher einen Wert einer Variablen zurückgibt. Performance dürfte daher praktisch identisch sein (abhängig vom jeweiligen Overhead), aber obs funktioniert kann man so nicht sagen. Marshal.GetLastWin32Error ist eigentlich (nur) für Verwendung nach P-Invoke gedacht.
Ähnliche Themen
-
Fenster mit anderem Thread öffnen
Von Knight_Rider im Forum .NET Windows FormsAntworten: 2Letzter Beitrag: 05.01.08, 19:07 -
AsyncSocket in Thread schliessen
Von Dipsi im Forum VisualStudio & MFCAntworten: 3Letzter Beitrag: 13.03.07, 07:06 -
Socket schliessen
Von MaLb im Forum JavaAntworten: 4Letzter Beitrag: 29.12.06, 11:28 -
Socket schliessen
Von DerKleineVomSee im Forum JavaAntworten: 12Letzter Beitrag: 13.06.06, 15:52





Zitieren
Login




