У меня есть система связи, основанная на TcpClient, и она прекрасно работает, за исключением случаев, когда она делает HTTPS для определенного IP. Тогда это начинает терпеть неудачу.
Используя браузер или HttpWebRequest, у меня нет проблем с HTTPS для этого IP-адреса.
Я создал тестовую программу, чтобы сузить мою проблему до ее основной сути, вы можете посмотреть ее здесь, если хотите: TestViaTcp
Эта тестовая программа отлично работает для базового HTTP на тот же IP, она всегда выдает успешный ответ на запрос. Я помещаю это в цикл, запускаю его нажатием клавиши, и оно будет продолжаться весь день. Как только я переключаю 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, которое я получаю? Есть ли какой-нибудь способ получить поведение «всегда работает», которое я вижу, когда выполняю HTTPS с HttpWebRequest?
Должно быть что-то, что я могу сделать с TcpClient, чтобы заставить его действовать и реагировать так же, как это делает HttpWebRequest, но я еще не там. Есть идеи?
Примечание. Сервер, с которым я общаюсь, настраивается в зависимости от того, какой порт он слушает, и какого протокола он ожидает, но в остальном он совершенно не поддается изменению.
Также обратите внимание: я читал, что в .net 3.5 была эта специфическая проблема с SslStream до SP1, но у меня есть SP1, и моя программа построена на 3.5, поэтому я предполагаю, что это не «известная ошибка» «Я сталкиваюсь здесь.