2

私はTcpClientに基づく通信システムを持っています、そしてそれが特定のIPにHTTPSをしているときを除いてそれはうまく働きます。その後、失敗し始めます。

ブラウザまたはHttpWebRequestを使用することで、そのIPに対してHTTPSを実行することに問題はありません。

私は問題をその基本的な本質に絞り込むためのテストプログラムを作成しました。必要に応じて、ここでそれを見ることができます:TestViaTcp

このテストプログラムは、同じIPへの基本HTTPに対して完全に機能し、要求に対して常に正常な応答を生成します。私はそれをループに入れ、キーを押すことでトリガーします、それは一日中成功し続けます。HTTPSを切り替えるとすぐに、繰り返しパターンが発生します。それはうまくいくでしょう、そしてそれはうまくいきません、成功、失敗、そして一日中成功が続きます。

私が得続ける特定の失敗はこれです:

{"Authentication failed because the remote party has closed the transport stream."}
    [System.IO.IOException]: {"Authentication failed because the remote party has closed the transport stream."}
    Data: {System.Collections.ListDictionaryInternal}
    HelpLink: null
    InnerException: null
    Message: "Authentication failed because the remote party has closed the transport stream."
    Source: "System"
    TargetSite: {Void StartReadFrame(Byte[], Int32, System.Net.AsyncProtocolRequest)}

そして、これに添付されているスタックトレースは次のとおりです。

   at System.Net.Security.SslState.StartReadFrame(Byte[] buffer, Int32 readBytes, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartReceiveBlob(Byte[] buffer, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.ForceAuthentication(Boolean receiveFirst, Byte[] buffer, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.ProcessAuthentication(LazyAsyncResult lazyResult)
   at System.Net.Security.SslStream.AuthenticateAsClient(String targetHost, X509CertificateCollection clientCertificates, SslProtocols enabledSslProtocols, Boolean checkCertificateRevocation)
   at DeriveClassNameSpace.Services.Web.TcpMessaging.TestViaTcp(IPEndPoint endpoint, String auth, Boolean useSSL)

HttpWebRequestとブラウザはどちらも(IIRC)Win32ライブラリを使用してやり取りを処理しますが、TcpClientは(AFAIK)マネージド.net Socketクラスを使用するため、両者には大きな違いがあると確信しています。TcpClientでこれを行う必要があるので、残念ながら、「HttpWebRequestを機能させることができるとわかっているので、使用する」ことはできません。

ここで問題が何であるかについての最大のヒントは、おそらく「機能する、機能しない、機能する、機能しない」パターンですが、それを引き起こしているのは何ですか?発生しているIOExceptionを回避するにはどうすればよいですか?HttpWebRequestを使用してHTTPSを実行したときに表示される、「常に機能する」動作を取得する方法はありますか?

TcpClientを使用して、HttpWebRequestと同じように動作させ、反応させるためにできることがあるはずですが、まだそこにはいません。何か案は?

注:私が通信しているサーバーは、リッスンするポートと期待するプロトコルに関して構成可能ですが、それ以外の場合は完全に変更できません。

また、注意:.net 3.5ではSP1より前のSslStreamでこの特定の問題が発生したことを読みましたが、SP1があり、プログラムは3.5をターゲットにして構築されているため、これは「既知のバグ」ではないと想定しています。 mここにぶつかる。

4

1 に答える 1

3

私が質問を形成するのに時間を費やした後、私が答えにつまずいたとき、あなたはそれを知らないでしょう。

関連するドキュメントは次のとおりです。jpsandersブログエントリ

重要な部分はこれでした:

例外のスタックに次のようなものが含まれている場合:System.IO.IOException:リモートパーティがトランスポートストリームを閉じたため、認証に失敗しました。サーバーが古いサーバーである可能性があり、TLSを認識しないため、915599 kbで指定されているように、ServicePointManager.SecurityProtocol=SecurityProtocolType.Ssl3;アプリケーションでHTTPS呼び出しを行う前にこれを変更する必要があります。

そこで、受け入れたプロトコルを次のように変更します:( TLSの可能性を排除します)

SslProtocols protocol = SslProtocols.Ssl2 | SslProtocols.Ssl3;

そして、すべてがうまく機能します。
TLSを許可していたので、最初にTLSを試行しますが、サーバーはTLSをサポートしていないため、ストリームは閉じられます。次回はSsl2またはSsl3を使用し、すべて問題ありません。またはそのようなもの。それはうまくいきます、私は幸せなパンダです。

于 2010-06-29T17:49:26.020 に答える