Reputation: 101
I'm writing a socket application that asynchronously polls several servers at once and reports any changes in their states to the user. So far everything is working, except for one small bug I can't seem to figure out.
The server creates a bunch of sockets every 10 seconds, then calls an async connect. This is then handled by a ProcessConnectionComplete(IAsyncResult iar) method, which then calls both Socket.BeginReceive and then Socket.Begin send. Any received data is then handled with another method.
Then, at the end of the 10 seconds before the next wave of sockets is created, any sockets that have not already received data and closed are forcefully closed by a loop.
The issue I am having is that if the socket happens to close just before the Socket.BeginSend method is called (ie someone trips over a network cable, or the server on the other end crashes), the program exits without exeption (error code 0), when it should throw an exception. Here's the code:
private static void ProcessConnectionComplete(IAsyncResult iar)
{
SocketState state = iar.AsyncState as SocketState;
if (state.Socket.Connected)
{
// start waiting for a reply
state.Socket.BeginReceive(state.Buffer, 0, state.Buffer.Length, SocketFlags.None, new AsyncCallback(frm_Server_Poll.ProcessAsyncReceive), state);
//state.Socket.Close(); // if socket is closed after .Connected check and before BeginSend, crash occurs
try
{
// send message
state.Socket.BeginSend(new byte[] { (byte)'\xfe' }, 0, 1, SocketFlags.None, null, state);
}
catch (Exception ex) // Never called, EXCEPTION WHERE ARE YOU???
{
throw (ex);
}
}
else
{
state.ServerInfo.connected = false;
}
}
Why is this happening? I have some idea that it is to do with the way threading is handled with Async calls, but have no idea how to catch the exception. Any help would be greatly appreciated.
Upvotes: 2
Views: 3230
Reputation: 310840
if the socket happens to close just before the Socket.BeginSend method is called (ie someone trips over a network cable, or the server on the other end crashes)
I do not understand. Neither of those events will close your socket. Only you can close your socket. Those events can abort the connection, in which case your send will get whatever exception an ECONNRESET maps to in C#. If you close the socket yourself and then send, you will get whatever EBADF maps to if nothing else in C# traps it first.
Upvotes: 0
Reputation: 6479
The exception should occur in the callback (frm_Server_Poll.ProcessAsyncReceive
) when calling Socket.EndReceive
.
Likewise, for the send, the exception should occur in its callback when calling Socket.EndSend
. However, your BeginSend
does not have a callback with which to handle errors.
I cannot be certain, but I suspect that this is why the exception is getting mysteriously lost.
It's worth noting that both BeginReceive
and BeginSend
can throw directly if the socket is disposed at the time they are called.
Upvotes: 1