我有一个基于 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 构建的,所以我假设这不是“已知错误”我我跑到这里。