为什么WSARecvMsg函数是作为函数指针实现的,这个指针可以被重用吗?

这里描述的WSARecvMsg函数要求您检索一个函数指针,如下面的引用所示:

注意必须在运行时通过使用指定的SIO_GET_EXTENSION_FUNCTION_POINTER操作码调用WSAIoctl函数来获取WSARecvMsg函数的函数指针。

这是否有特定的原因? 在使用这个函数的时候,我打算在启动的时候检索函数指针,然后一直使用它。 这种方法有什么问题吗? 关于函数的任何改变都意味着我们需要重新获取这个指针,我们怎么知道这是否是这种情况呢?

根据WSARecvMsg()文档 :

注意此函数是Windows套接字规范的Microsoft特定扩展

根据WSAIoctrl()文档 :

SIO_GET_EXTENSION_FUNCTION_POINTER(操作码设置:O,I,T == 1)
检索指向相关服务提供者支持的指定扩展功能的指针 。 输入缓冲区包含一个全局唯一标识符(GUID),其值标识所讨论的扩展函数。 指向所需函数的指针在输出缓冲区中返回。 扩展功能标识符由服务提供商供应商建立,应包含在描述扩展功能和语义的供应商文档中。

在大多数系统上,微软的提供者是唯一安装的提供者。 但是,第三方提供商确实存在(自定义TCP堆栈等),也可能被安装。 根据WSAStartup()WSADATA文档:

Windows套接字的体系结构在版本2中更改为支持多个提供程序 ,而WSADATA不再适用于单个供应商的堆栈。

其中进一步支持:

Windows套接字2架构

特定于提供者的扩展机制

当你使用socket()创建一个套接字时,你不能控制使用哪个提供者。 当您使用WSASocket()创建套接字时,您可以通过lpProtocolInfo参数指定特定的提供者。

WSARecvMsg()仅在Microsoft的提供程序中可用,因此您必须将它传递WSARecvMsg()同一提供程序关联的SOCKETWSAIoctrl()可用于将命令发送到SOCKET所属的提供程序。 因此,通过使用SIO_GET_EXTENSION_FUNCTION_POINTER ,您可以确保WSARecvMsg() (或任何其他供应商特定的函数)由指定SOCKET的提供者支持,因此与该SOCKET兼容。

微软的供应商通过WSAIoctrl() 1提供的其他微软特定功能是:

  • AcceptEx()
  • ConnectEx()
  • DisconnectEx()
  • GetAcceptExSockAddrs()
  • TransmitFile()
  • TransmitPackets()
  • WSASendMsg()

一旦检索到指向特定于供应商的函数的指针,只要提供程序保持加载到内存中(在第一次调用WSAStartup()和最后一次调用WSACleanup() ),就可以随意使用指针了。并且将它传递给属于该提供者的SOCKET

1 :每个提供商特定的扩展机制

在Windows Vista和更高版本中, 新的Winsock系统扩展从Winsock DLL直接导出,所以WSAIoctl函数不需要加载这些扩展 。 Windows Vista和更高版本中提供的新扩展功能包括从Ws2_32.dll导出的WSAPollWSASendMsg函数。