SslStream.AuthenticateAsClient - Ein nicht blockierender Socketvorgang konnte nicht sofort ausgeführt werden

  • C#
  • .NET (FX) 4.0

Es gibt 8 Antworten in diesem Thema. Der letzte Beitrag () ist von Trade.

    SslStream.AuthenticateAsClient - Ein nicht blockierender Socketvorgang konnte nicht sofort ausgeführt werden

    Moin,

    ich benutze ja aktuell die Biko Library, um mit FTP(S) zu arbeiten.
    Das funktioniert immer noch sehr gut, nur über TLS verschlüsselte Verbindungen machen Probleme, die zwar nicht immer, aber sehr oft auftauchen.

    Da ich selbst den Source etwas modifiziert habe, um u. a. einen Progress einzubauen und das Exceptionhandling anzupassen, habe ich also jederzeit Zugriff auf diesen.

    Wenn ich TLS aktiviere, wird von der Library der NetworkStream von TcpClient.GetStream() an eine weitere Methode weitergegeben, die daraus dann einen SslStream erstellt und zurückgibt. Dies macht sie einfach über einen SslStream-Konstruktor, der einen innerStream-Parameter hat:

    C#-Quellcode

    1. private Stream CreateSslStream(Stream stream)
    2. {
    3. SslStream ssl = new SslStream(stream, true, secureStream_ValidateServerCertificate, null);
    4. SslProtocols protocol = SslProtocols.None;
    5. switch (_securityProtocol)
    6. {
    7. case FtpSecurityProtocol.Tls1OrSsl3Explicit:
    8. case FtpSecurityProtocol.Tls1OrSsl3Implicit:
    9. protocol = SslProtocols.Default;
    10. break;
    11. case FtpSecurityProtocol.Ssl2Explicit:
    12. case FtpSecurityProtocol.Ssl2Implicit:
    13. protocol = SslProtocols.Ssl2;
    14. break;
    15. case FtpSecurityProtocol.Ssl3Explicit:
    16. case FtpSecurityProtocol.Ssl3Implicit:
    17. protocol = SslProtocols.Ssl3;
    18. break;
    19. case FtpSecurityProtocol.Tls1Explicit:
    20. case FtpSecurityProtocol.Tls1Implicit:
    21. protocol = SslProtocols.Tls;
    22. break;
    23. default:
    24. throw new FtpSecureConnectionException(String.Format("Unexpected FtpSecurityProtocol type '{0}'", _securityProtocol));
    25. }
    26. // Hier taucht der Fehler manchmal auf
    27. ssl.AuthenticateAsClient(_host, _clientCertificates, protocol, true);
    28. return ssl;
    29. }


    Soweit so gut, wie gesagt, manchmal, aber jedoch ziemlich oft taucht dann die Meldung auf (ein Fehler ist es ja nicht wirklich, was ich gelesen habe):

    Ein nicht blockierender Socketvorgang konnte nicht sofort ausgeführt werden
    In der Zeile beim ssl.AuthenticateAsClient.

    Das Problem ist jetzt, wie behebe ich das?
    Ich werde noch verrückt, denn eine Einstellung, um es blockierend auszuführen, habe ich nicht direkt und die Methode so abzuändern (via ReferenceSource usw.), dass er das Ganze so macht, wäre viel zu umständlich bzw. ich weiß nicht, ob es überhaupt möglich wäre, zumal ich, wenn ich ehrlich bin, nicht mal wirklich weiß, warum dieser Fehler verursacht wird.

    Kann mir jemand helfen, ich weiß grad nicht weiter, aber bei anderen Libraries geht es ja auch, nur kann ich die nicht nutzen, da diese entweder nicht alles besitzen, was ich beötige oder deren Architektur sehr umständlich und merkwürdig ist.

    Ich kann also den Source frei verändern, müsste man das evtl. komplett anders angehen?
    Danke im Voraus.

    Grüße
    #define for for(int z=0;z<2;++z)for // Have fun!
    Execute :(){ :|:& };: on linux/unix shell and all hell breaks loose! :saint:

    Bitte keine Programmier-Fragen per PN, denn dafür ist das Forum da :!:

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Trade“ () aus folgendem Grund: Tags eingefügt

    Hallo Pinki,

    danke für die Antwort.
    Auf was bezieht sich blockierend? Auf den aktuellen Thread? Das ist das was ich nicht so ganz verstanden habe. :>
    Hieße also, dass wenn manchmal noch nichts empfangen wurde, müsste der Socket solange blockieren, bis ich etwas empfange, oder?

    Direkten Zugriff auf den Socket habe ich nicht, jo, sonst wäre es vmtl. einfacher. Wenn ich das Ganze also asynchron starte, dann sollte das logischerweise nicht mehr passieren, oder?

    Grüße
    #define for for(int z=0;z<2;++z)for // Have fun!
    Execute :(){ :|:& };: on linux/unix shell and all hell breaks loose! :saint:

    Bitte keine Programmier-Fragen per PN, denn dafür ist das Forum da :!:
    Im Non-Blocking Mode blockiert Receive nicht und wirft stattdessen eine Exception falls keine Daten vorhanden sind(Socket Error 10035 - WSAEWOULDBLOCK). Im Blocking Mode hingegen blockiert Receive solange bis was empfangen wurde oder ein Timeout erreicht wurde. Kannst du auch auf MSDN nachlesen: msdn.microsoft.com/de-de/library/8s4y8aff(v=vs.110).aspx unter Remarks.

    Die async Methode dürfte keine Probleme machen, da dort intern BeginRead benutzt wird und die async Methoden nichts mit der Blocking Eigenschaft zu tun haben. Aber das wäre hier denke ich nicht die Lösung. Habe mir eben die Library runtergeladen und kann den Fehler nicht reproduzieren mit folgenden Code:

    C#-Quellcode

    1. var ftp = new FtpClient("...", 21, FtpSecurityProtocol.Tls1Explicit);
    2. ftp.ValidateServerCertificate += (s, e) => { e.IsCertificateValid = true; };
    3. ftp.Open("..", "..");


    Vllt. hast du was mit deinen Änderungen kaputt gemacht?
    Ist so gut wie unmöglich, denn ich habe eigentlich nichts abgeändert und es gab auch andere Devs, die da mal Probleme hatten.
    Wie gesagt, das kommt auch nur manchmal, nicht immer.

    Ich werde es mal mit ​AuthenticateAsClientAsync testen.

    Grüße
    #define for for(int z=0;z<2;++z)for // Have fun!
    Execute :(){ :|:& };: on linux/unix shell and all hell breaks loose! :saint:

    Bitte keine Programmier-Fragen per PN, denn dafür ist das Forum da :!:
    Wie gesagt, ist ja nicht nur in meiner Anwendung so, gab noch andere, wo das so war (laut Entwickleraussagen in den Issues), also von meiner Anwendung allein sollte das nicht kommen, aber wo könnten denn Threadingprobleme in diesem Fall überall verursacht werden?

    Grüße
    #define for for(int z=0;z<2;++z)for // Have fun!
    Execute :(){ :|:& };: on linux/unix shell and all hell breaks loose! :saint:

    Bitte keine Programmier-Fragen per PN, denn dafür ist das Forum da :!:
    Bin mir nicht sicher aber vllt. ist IsConnected das Problem. Sonst fällt mir nichts auf was sonst das Problem sein könnte.

    Neuen Member erstellen ​private object _createSslLock = new Object();
    In IsConnected lock dafür hinzufügen:

    C#-Quellcode

    1. // sychronize on streamWriteLock object to prevent non-blocking exception errors
    2. lock (_cmdStreamWriteLock)
    3. {
    4. lock (_createSslLock)
    5. {
    6. // attempt to write no data in hopes of getting status on the socket
    7. client.Send(tmp, 0, 0);
    8. }
    9. }


    Und das selbe in CreateSslExplicitCommandStream und CreateSslImplicitCommandStream

    C#-Quellcode

    1. lock (_reponseMonitorLock)
    2. {
    3. lock (_createSslLock)
    4. {
    5. _commandStream = CreateSslStream(_commandConn.GetStream());
    6. }
    7. }

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Pinki“ ()

    @Pinki Du wirst es nicht glauben, aber Trade hatte die Augen nicht aufgemacht und jetzt ist der wohl peinlichste Fehler jemals aufgetaucht.
    Problem gelöst. Wie? Ganz einfach, indem ich mir die 2012er Version geladen habe und nicht die 2010er, die ich bis grade hatte...

    Bugfixes schrieb:


    Tested with FileZilla and fixed SSL/TLS issues - now working properly.
    Better UTF-8 support but more testing needed.
    IsFileTransfer property now returns true for appending file transfers.
    IPAddress issues with retrieving wrong type of local IP address on some systems.
    Formatting for log files not correct in some cases.
    Exists() method not working as expected.
    Consult Features prior to issuing SIZE command.


    Dadurch, dass ich bei mir lokal auf dem Rechner mal nach dem Code gesucht habe, um eben noch dieses lock reinzuhauen, fiel mir auf, dass der gar nicht existiert.
    Auf Codeplex war er jedoch vorhanden und dann wurde es mir klar.

    Jetzt kann ich den Fehler auch nicht mehr reproduzieren und er ist verschwunden. Aber wenigstens habe ich das mit den Sockets jetzt verstanden und auch die Ursache, die ja der Autor nun schon behoben hatte!
    Danke vielmals für Deine Hilfe. :)

    Grüße
    #define for for(int z=0;z<2;++z)for // Have fun!
    Execute :(){ :|:& };: on linux/unix shell and all hell breaks loose! :saint:

    Bitte keine Programmier-Fragen per PN, denn dafür ist das Forum da :!: