Я написал веб-сервис, который является Asp. Net MVC приложением, размещенным в IIS. Данные из веб-службы извлекаются не из базы данных, а с другого сервера, доступ к которому осуществляется через TCP. Мы будем называть это сервером данных. Может быть несколько серверов данных, к которым подключается веб-служба.
Для обсуждения пользователь аутентифицируется, указав имя пользователя и пароль, после чего с соответствующим сервером данных создается сеанс с сокетом. Предполагая, что все хорошо - мы поддерживаем Socket в рабочем состоянии и передаем пользователю токен, который идентифицирует сеанс, к которому он принадлежит.
Для каждого сокета мне нужно предотвратить, чтобы traffi c не прерывал друг друга. Я предполагаю, что лучший способ сделать это - запустить сетевой трафик c на Socket в последовательной форме. Я добился этого с помощью блокировки. Мой код для выполнения запроса на этом сервере данных следующий. У меня проблема в том, что время от времени кажется, что я получаю два запроса, которые сталкиваются, и один может зависнуть. Я вижу, как поступает запрос, но похоже, что он застрял в замке. Безопасен ли механизм блокировки для вызовов IIS asyn c? Могу ли я установить инструментарий, чтобы убедиться, что это действительно ошибка? Я долго искал, но не могу найти руководство для этого конкретного сценария.
private async Task<string> query(string request, AbstractPermission context = null, bool bUpdateDateTime = true)
{
try
{
string reply = "";
isErrorMsg = false;
//this lock prevents the keep alive thread from coming in here while we're on the socket
lock (socketLock)
{
sendDone.Reset();
receiveDone.Reset();
// Send test data to the remote device.
Send(Socket, request);
sendDone.WaitOne();
// Receive the response from the remote device.
Receive(Socket);
receiveDone.WaitOne();
reply = QueryResponse;
} //done reading - let's unlock
if (bUpdateDateTime)
{
this.LastUsed = DateTime.Now;
}
return QueryResponse;
}
catch (Exception e)
{
throw e;
}
}
private void Send(Socket client, String data)
{
byte[] byteData = Encoding.ASCII.GetBytes(data);
client.BeginSend(byteData, 0, byteData.Length, 0,
new AsyncCallback(SendCallback), client);
}
private void SendCallback(IAsyncResult ar)
{
try
{
// Retrieve the socket from the state object.
Socket client = (Socket)ar.AsyncState;
// Complete sending the data to the remote device.
int bytesSent = client.EndSend(ar);
// Signal that all bytes have been sent.
sendDone.Set();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
private void Receive(Socket client)
{
try
{
// Create the state object.
StateObject state = new StateObject();
state.workSocket = client;
state.PostInitialRead = false;
// Begin receiving the data from the remote device.
client.BeginReceive(state.buffer, 0, StateObject.BufferSize, SocketFlags.None,
new AsyncCallback(ReceiveCallback), state);
}
catch (Exception e)
{
LogError(e);
}
}
private void ReceiveCallback(IAsyncResult ar)
{
try
{
// Retrieve the state object and the client socket
// from the asynchronous state object.
StateObject state = (StateObject)ar.AsyncState;
Socket client = state.workSocket;
bool PostInitialRead = state.PostInitialRead;
// Read data from the remote device.
int bytesRead = client.EndReceive(ar);
//
//
var thisBatch = Encoding.ASCII.GetString(state.buffer, 0, bytesRead);
var endIdx = thisBatch.IndexOf('\x04');
if (!PostInitialRead)
{
if (bytesRead == 0)
throw new ApplicationException("Timeout waiting for response");
if (endIdx != -1)
{
thisBatch = thisBatch.Substring(0, endIdx);
}
if (state.buffer[0] != 0)
{
thisBatch = thisBatch.Substring(1, state.buffer[0]);
isErrorMsg = true;
}
else if (state.buffer[1] != 0)
{
thisBatch = thisBatch.Substring(2);
isErrorMsg = true;
}
else
{
thisBatch = thisBatch.Substring(2);
}
state.sb.Append(thisBatch);
state.PostInitialRead = true;
}
else
{
state.ms.Write(state.buffer, 0, endIdx!=-1?endIdx:bytesRead);
}
if (endIdx != -1)
{
// Got everything
state.sb.Append(Encoding.ASCII.GetString(state.ms.ToArray()));
QueryResponse = state.sb.ToString();
receiveDone.Set();
return;
}
else
{
// Get the rest of the data.
client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReceiveCallback), state);
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}