WSAEventSelect模型

时间:2009-08-25 07:31:55

标签: c++ winsock

嘿,我正在使用WSAEventSelect进行套接字的事件通知。到目前为止,一切都很酷,工作就像一个魅力,但有一个问题。

客户端是.NET应用程序,服务器是用Winsock C ++编写的。在.NET应用程序中,我使用TCP / IP的System.Net.Sockets.Socket类。当我调用Socket.Shutdown()和Socket.Close()方法时,我在服务器中收到FD_CLOSE事件,我很确定这很好。好的,当我检查传递给WSAEnumNetworkEvents的WSANETWORKEVENTS的iErrorCode时会出现问题。我这样检查

if (listenerNetworkEvents.lNetworkEvents & FD_CLOSE)
    {
        if (listenerNetworkEvents.iErrorCode[FD_CLOSE_BIT] != 0)
        {
            // it comes here
            // which means there is an error
            // and the ERROR I got is
            // WSAECONNABORTED
            printf("FD_CLOSE failed with error %d\n", 
                listenerNetworkEvents.iErrorCode[FD_CLOSE_BIT]);
            break;
        }

        closesocket(socketArray[Index]);
}

但它因 WSAECONNABORTED 错误而失败。为什么会这样?

编辑:顺便说一句,我在同一台计算机上运行客户端和服务器,是不是因为这个?当我这样做时,我收到了FD_CLOSE事件:

server.Shutdown(SocketShutdown.Both);   // in .NET C#, client code

1 个答案:

答案 0 :(得分:2)

我猜你正在调用Shutdown()然后立即关闭()。这将给出你所看到的症状,因为这是“关闭连接”。 Shutdown()确实启动了一个正常的断开连接(TCP FIN),但是紧跟其后用Close()中止,将TCP RST数据包发送到远程对等体。顺便说一句,你的Shutdown(SocketShutdown.Both)调用也会关闭连接。

正确的模式是:

  1. 调用Shutdown()并将direction参数设置为“write”,这意味着我们不会向远程对等方发送更多数据。这会导致堆栈发送TCP FIN数据包。

  2. 回去等待Winsock事件。当远程对等体也完成写入时,它也将调用Shutdown(“write”),导致其堆栈向您的机器发送TCP FIN数据包,并为您的应用程序获取FD_CLOSE事件。等待时,您的代码应准备好继续从套接字读取,因为远程对等方可能仍在发送数据。

  3. (请原谅上面的伪C#。我不会说.NET,只有C ++。)

    两个对等体都应该使用相同的关闭模式:每个对象在完成写入时告诉对方,然后在关闭其套接字之前等待接收远程对等体完成写入的通知。

    要实现的重要一点是TCP是双向协议:每一方都可以独立于另一方发送和接收。关闭套接字阅读并不是一件好事。这就像与另一个人交谈,但只是说话而不愿意倾听。优雅的关机协议说:“我现在已经说完了。我要等到你走开之前你就停止说话了。”