P
Pete Davis
I'm writing an Nntp library and I've run into a problem that I've run into
before with async sockets. I fixed it before, but I don't remember how and
I'm running out of ideas this time.
My receive code is below. My question follows:
private NntpStatusResponse ReceiveData(CallbackType callbackType)
{
SocketState state = new SocketState();
// Receive the first block
_receiveEvent.Reset();
_nntpClient.BeginReceive(state.TempBuffer, 0, state.TempBuffer.Length,
SocketFlags.None, new AsyncCallback(ReceiveCallback), state);
_receiveEvent.WaitOne();
if (null != state.Response)
{
return state.Response;
}
throw new NntpException("ReceiveData failed without a response");
}
private void ReceiveCallback(IAsyncResult asyncResult)
{
SocketState state = (SocketState) asyncResult.AsyncState;
int bytesReceived = _nntpClient.EndReceive(asyncResult);
if (!state.StatusReceived)
{
if (bytesReceived < 3)
{
throw new NntpException("Invalid response from server");
}
string strBuffer = Encoding.Default.GetString(state.TempBuffer, 0,
bytesReceived);
int statusCode = Convert.ToInt32(strBuffer.ToString().Substring(0,3));
int lineBreak = strBuffer.IndexOf(NNTPNewLine);
string statusText = strBuffer.Substring(3, strBuffer.Length - 3);
statusText = statusText.Trim();
if (lineBreak >= 0)
{
lineBreak += NNTPNewLine.Length;
strBuffer = strBuffer.Substring(lineBreak, strBuffer.Length -
lineBreak);
state.ResultBuffer.Append(strBuffer);
state.Response = new NntpStatusResponse(statusCode, statusText, null);
}
}
else
{
if (0 != bytesReceived)
{
string strBuffer = Encoding.Default.GetString(state.TempBuffer, 0,
bytesReceived);
state.ResultBuffer.Append(strBuffer);
}
}
if (bytesReceived < BufferSize)
{
string[] responseArray =
state.ResultBuffer.ToString().Split(NNTPNewLine.ToCharArray());
if (responseArray.Length > 1)
{
string newResponseStr = responseArray[responseArray.Length - 1];
state.Response = new NntpStatusResponse(state.Response.StatusCode,
state.Response.StatusText, responseArray);
}
}
else
{
_nntpClient.BeginReceive(state.TempBuffer, 0, state.TempBuffer.Length,
SocketFlags.None, new AsyncCallback(ReceiveCallback), state);
}
_receiveEvent.Set();
}
The code blocks on the second receive at the EndReceive() call.
The first time through, it works perfectly. According the Ethereal, the
second message arrives, but the socket blocks on the EndReceive for the
second message, so I can't process it.
I believe my ManualResetEvent is set up correctly. Why would EndReceive()
block?
Thanks.
Pete
before with async sockets. I fixed it before, but I don't remember how and
I'm running out of ideas this time.
My receive code is below. My question follows:
private NntpStatusResponse ReceiveData(CallbackType callbackType)
{
SocketState state = new SocketState();
// Receive the first block
_receiveEvent.Reset();
_nntpClient.BeginReceive(state.TempBuffer, 0, state.TempBuffer.Length,
SocketFlags.None, new AsyncCallback(ReceiveCallback), state);
_receiveEvent.WaitOne();
if (null != state.Response)
{
return state.Response;
}
throw new NntpException("ReceiveData failed without a response");
}
private void ReceiveCallback(IAsyncResult asyncResult)
{
SocketState state = (SocketState) asyncResult.AsyncState;
int bytesReceived = _nntpClient.EndReceive(asyncResult);
if (!state.StatusReceived)
{
if (bytesReceived < 3)
{
throw new NntpException("Invalid response from server");
}
string strBuffer = Encoding.Default.GetString(state.TempBuffer, 0,
bytesReceived);
int statusCode = Convert.ToInt32(strBuffer.ToString().Substring(0,3));
int lineBreak = strBuffer.IndexOf(NNTPNewLine);
string statusText = strBuffer.Substring(3, strBuffer.Length - 3);
statusText = statusText.Trim();
if (lineBreak >= 0)
{
lineBreak += NNTPNewLine.Length;
strBuffer = strBuffer.Substring(lineBreak, strBuffer.Length -
lineBreak);
state.ResultBuffer.Append(strBuffer);
state.Response = new NntpStatusResponse(statusCode, statusText, null);
}
}
else
{
if (0 != bytesReceived)
{
string strBuffer = Encoding.Default.GetString(state.TempBuffer, 0,
bytesReceived);
state.ResultBuffer.Append(strBuffer);
}
}
if (bytesReceived < BufferSize)
{
string[] responseArray =
state.ResultBuffer.ToString().Split(NNTPNewLine.ToCharArray());
if (responseArray.Length > 1)
{
string newResponseStr = responseArray[responseArray.Length - 1];
state.Response = new NntpStatusResponse(state.Response.StatusCode,
state.Response.StatusText, responseArray);
}
}
else
{
_nntpClient.BeginReceive(state.TempBuffer, 0, state.TempBuffer.Length,
SocketFlags.None, new AsyncCallback(ReceiveCallback), state);
}
_receiveEvent.Set();
}
The code blocks on the second receive at the EndReceive() call.
The first time through, it works perfectly. According the Ethereal, the
second message arrives, but the socket blocks on the EndReceive for the
second message, so I can't process it.
I believe my ManualResetEvent is set up correctly. Why would EndReceive()
block?
Thanks.
Pete