如果在套接字关闭后调用 Socket.BeginSend,则应用程序崩溃而不引发异常

发布于 2024-12-10 03:04:50 字数 1320 浏览 4 评论 0原文

我正在编写一个套接字应用程序,它可以同时异步轮询多个服务器并向用户报告其状态的任何变化。到目前为止,一切正常,除了一个我似乎无法弄清楚的小错误。

服务器每 10 秒创建一组套接字,然后调用异步连接。然后由 ProcessConnectionComplete(IAsyncResult iar) 方法处理,该方法随后调用 Socket.BeginReceive 和 Socket.Begin send。然后使用另一种方法处理任何接收到的数据。

然后,在创建下一波套接字之前的 10 秒结束时,任何尚未接收到数据并关闭的套接字将被循环强制关闭。

我遇到的问题是,如果套接字恰好在调用 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;
    }
}

为什么会发生这种情况?我有一些想法,这与异步调用处理线程的方式有关,但不知道如何捕获异常。任何帮助将不胜感激。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

仅冇旳回忆 2024-12-17 03:04:50

调用 Socket.EndReceive 时,异常应该发生在回调 (frm_Server_Poll.ProcessAsyncReceive) 中。

同样,对于发送,调用Socket.EndSend时的回调中应该发生异常。但是,您的 BeginSend 没有用于处理错误的回调。

我不能确定,但​​我怀疑这就是异常神秘丢失的原因。

值得注意的是,如果调用时套接字已被释放,则 BeginReceiveBeginSend 都可以直接抛出异常。

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.

揪着可爱 2024-12-17 03:04:50

如果套接字恰好在 Socket.BeginSend 方法之前关闭
被调用(即有人被网线绊倒,或者服务器上的
另一端崩溃)

我不明白。这些事件都不会关闭您的套接字。只有您可以关闭套接字。这些事件可以中止连接,在这种情况下,您的发送将收到 ECONNRESET 在 C# 中映射到的任何异常。如果您自己关闭套接字然后发送,如果 C# 中没有其他内容先捕获它,您将获得 EBADF 映射到的任何内容。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文