Сбой приложения без исключения, если Socket.BeginSend вызывается после закрытия сокета - PullRequest
2 голосов
/ 13 октября 2011

Я пишу приложение для сокетов, которое асинхронно опрашивает несколько серверов одновременно и сообщает о любых изменениях их состояний пользователю.Пока все работает, кроме одной маленькой ошибки, которую я не могу понять.

Сервер создает группу сокетов каждые 10 секунд, а затем вызывает асинхронное соединение.Затем это обрабатывается методом ProcessConnectionComplete (IAsyncResult iar), который затем вызывает и Socket.BeginReceive, а затем Socket.Begin send.Любые полученные данные затем обрабатываются другим методом.

Затем, в конце 10 секунд до создания следующей волны сокетов, любые сокеты, которые еще не получили данные и закрыты, принудительно закрываются циклом.

Проблема Iу меня есть то, что, если сокет случается закрыться непосредственно перед вызовом метода Socket.BeginSend (т.е. кто-то спотыкается по сетевому кабелю, или сервер на другом конце падает), программа завершается без исключения (код ошибки 0), когдаэто должно вызвать исключение.Вот код:

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;
    }
}

Почему это происходит?У меня есть идея, что это связано со способом обработки потоков с помощью асинхронных вызовов, но я не знаю, как перехватить исключение.Любая помощь будет принята с благодарностью.

Ответы [ 2 ]

1 голос
/ 13 октября 2011

Исключение должно происходить в обратном вызове (frm_Server_Poll.ProcessAsyncReceive) при вызове Socket.EndReceive.

Аналогично, для отправки исключение должно происходить в своем обратном вызове при вызове Socket.EndSend.Однако ваш BeginSend не имеет функции обратного вызова для обработки ошибок.

Я не могу быть уверен, но я подозреваю, что именно поэтому исключение таинственным образом теряется.

Оно того стоитотмечая, что и BeginReceive, и BeginSend могут бросать напрямую, если сокет находится в момент их вызова.

0 голосов
/ 14 октября 2011

если сокет закрывается непосредственно перед вызовом метода Socket.BeginSend (то есть кто-то спотыкается по сетевому кабелю или сервер на другом конце падает)не понял.Ни одно из этих событий не закроет ваш сокет.Только ты можешь закрыть свою розетку.Эти события могут прервать соединение, и в этом случае ваша посылка получит любое исключение, которое ECONNRESET отображает в C #.Если вы сами закроете сокет, а затем отправите, вы получите все, что соответствует EBADF, если ничего в C # не перехватит его первым.

...