Статус: Участник
Группы: Участники
Зарегистрирован: 13.03.2008(UTC) Сообщений: 24 Откуда: Russia
|
Есть .NET-клиент, который отправляет запросы по HTTPS, используя стандартный WebRequest; и HTTP-сервер на HttpListener'е. Периодически, при обращении к серверу в несколько потоков, клиент впадает в ступор: на каждую попытку запроса к серверу в лог валится следующая ошибка: Код:System.Net.WebException: The underlying connection was closed: An unexpected error occurred on a receive. ---> System.ComponentModel.Win32Exception: The Local Security Authority cannot be contacted
at System.Net.SSPIWrapper.AcquireCredentialsHandle(SSPIInterface SecModule, String package, CredentialUse intent, SecureCredential scc)
at System.Net.Security.SecureChannel.AcquireCredentialsHandle(CredentialUse credUsage, SecureCredential& secureCredential)
at System.Net.Security.SecureChannel.AcquireClientCredentials(Byte[]& thumbPrint)
at System.Net.Security.SecureChannel.GenerateToken(Byte[] input, Int32 offset, Int32 count, Byte[]& output)
at System.Net.Security.SecureChannel.NextMessage(Byte[] incoming, Int32 offset, Int32 count)
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.TlsStream.CallProcessAuthentication(Object state)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Net.TlsStream.ProcessAuthentication(LazyAsyncResult result)
at System.Net.TlsStream.Write(Byte[] buffer, Int32 offset, Int32 size)
at System.Net.PooledStream.Write(Byte[] buffer, Int32 offset, Int32 size)
at System.Net.ConnectStream.WriteHeaders(Boolean async)
--- End of inner exception stack trace ---
at System.Net.HttpWebRequest.GetResponse()
При этом в Application-логе появляются соответствующие ошибки Крипто-Про: Код:КриптоПро TLS. Ошибка 0x8009001a при обращении к CSP: Keyset as registered is invalid.
Type: Error
Source: cpSSPCore
EventID: 300
Лечится только перезапуском клиента. WinXP SP3, .NET Framework SP2, Crypto-Pro 3.0 SP3. Ниже - тестовый сервер и клиент, с помощью которых можно воспроизвести ошибку. По-видимому, чем больше потоков, тем больше вероятность падения. На тестовой машинке при 32 потоках - падает стабильно. При этом, если уж работает - то без ошибок до перезапуска. Клиент:Код:using System;
using System.Net;
using System.Security.Cryptography.X509Certificates;
using System.Threading;
namespace Client
{
internal class Program
{
private static void Main(string[] args)
{
int threadsCount = int.Parse(args[0]);
serviceUriString = args[1];
certCommonName = args[2];
Thread[] threads = new Thread[threadsCount];
for(int i = 0; i < threadsCount; i++)
{
threads[i] = new Thread(Start);
threads[i].Start();
}
for(int i = 0; i < threadsCount; i++)
threads[i].Join();
}
private static void Start()
{
while(true)
{
try
{
Console.WriteLine("Sending request, thread: {0}", Thread.CurrentThread.ManagedThreadId);
CreateRequest().GetResponse().Close();
Thread.Sleep(1);
}
catch(Exception exception)
{
Console.WriteLine(exception);
}
}
}
private static HttpWebRequest CreateRequest()
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(string.Format("{0}?thread={1}", serviceUriString, Thread.CurrentThread.ManagedThreadId));
request.ClientCertificates.Add(GetCertificate(certCommonName));
request.ServicePoint.ConnectionLimit = 128;
request.Timeout = 60000;
return request;
}
private static X509Certificate GetCertificate(string commonName)
{
X509Store x509Store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
x509Store.Open(OpenFlags.ReadOnly);
foreach(X509Certificate2 x509Certificate in x509Store.Certificates)
{
string currentCommonName = x509Certificate.GetNameInfo(X509NameType.SimpleName, false);
if(currentCommonName == commonName)
return x509Certificate;
}
x509Store.Close();
throw new Exception("Cert not found");
}
private static string serviceUriString;
private static string certCommonName;
}
}
Сервер:Код: internal class Program
{
private static void Main(string[] args)
{
listener.Prefixes.Add(args[0]);
listener.Start();
listener.BeginGetContext(BeginProcessRequest, null);
Thread.Sleep(-1);
}
private static void BeginProcessRequest(IAsyncResult asyncResult)
{
listener.BeginGetContext(BeginProcessRequest, null);
HttpListenerContext context = listener.EndGetContext(asyncResult);
Console.WriteLine("{0}, beginGetClientCert", context.Request.RawUrl);
X509Certificate2 certificate = context.Request.GetClientCertificate();
if(certificate == null)
{
ShowStatusAndCloseRespose(context, 403);
return;
}
string certName = certificate.GetNameInfo(X509NameType.SimpleName, false);
Console.WriteLine("Cert: {0}, request: {1}", certName, context.Request.RawUrl);
context.Response.ContentType = "text/plain";
context.Response.ContentLength64 = 0;
ShowStatusAndCloseRespose(context, 204);
}
private static void ShowStatusAndCloseRespose(HttpListenerContext context, int statusCode)
{
Console.WriteLine("{0}, request: {1}", statusCode, context.Request.RawUrl);
context.Response.StatusCode = statusCode;
try
{
context.Response.Close();
}
catch
{}
}
private static readonly HttpListener listener = new HttpListener();
}
Отредактировано пользователем 19 июля 2010 г. 21:23:11(UTC)
| Причина: Не указана
|