C++ WSAEventSelect模型

C++ WSAEventSelect模型,c++,winsock,C++,Winsock,嘿,我正在使用WSAEventSelect进行套接字的事件通知。到目前为止,一切都很酷,工作起来很有魅力,但有一个问题 客户端是.NET应用程序,服务器是用Winsock C++编写的。在.NET应用程序中,我将System.NET.Sockets.Socket类用于TCP/IP。当我调用Socket.Shutdown()和Socket.Close()方法时,我在服务器中收到FD_Close事件,我很确定这是正确的。好的,当我检查我传递给WSAEnumNetworkEvents的WSANETWO

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

客户端是.NET应用程序,服务器是用Winsock C++编写的。在.NET应用程序中,我将System.NET.Sockets.Socket类用于TCP/IP。当我调用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

我猜您是在调用Shutdown()然后紧接着调用Close()。这将给出您所看到的症状,因为这是“砰的一声关闭连接”。Shutdown()确实会启动一个正常的断开连接(TCP FIN),但紧接着Close()会中止,并向远程对等方发送TCP RST数据包。顺便说一下,您的关机(SocketShutdown.Both)调用也会关闭连接

正确的模式是:

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

  • 返回等待Winsock事件。当远程对等方也完成写入时,它也将调用Shutdown(“write”),从而使其堆栈向您的计算机发送一个TCP-FIN数据包,并使您的应用程序获得FD_CLOSE事件。在等待时,您的代码应该准备好继续从套接字读取,因为远程对等方可能仍在发送数据

  • (请原谅上面的伪C,我不说.NET,只有C++)< /P> 两个对等方都应使用相同的关闭模式:每个对等方在完成写入时通知另一方,然后在关闭其套接字之前等待接收远程对等方已完成写入的通知

    重要的是要认识到TCP是一个双向协议:每一方都可以独立于另一方进行发送和接收。关闭套接字进行读取不是一件好事。这就像与另一个人交谈,但只是交谈,不愿意倾听。优雅的关机协议说:“我现在不说话了。我要等到你停止说话,我才会离开。”