为啥 WSARecvMsg 函数实现为函数指针,这个指针可以重复使用吗?

Posted

技术标签:

【中文标题】为啥 WSARecvMsg 函数实现为函数指针,这个指针可以重复使用吗?【英文标题】:Why is the WSARecvMsg function implemented as a function pointer and can this pointer be reused?为什么 WSARecvMsg 函数实现为函数指针,这个指针可以重复使用吗? 【发布时间】:2016-05-20 20:32:22 【问题描述】:

here 描述的 WSARecvMsg 函数要求您检索指向它的函数指针,如以下引用所示:

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

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

【问题讨论】:

似乎是 MSFT 的一个糟糕的设计理念。我看不出它有什么好处。 @SergeyA 我唯一的想法可能是硬件的变化或者某些东西可以改变这个功能???但是文档没有引用这样的内容,所以我不确定。 我唯一非常疯狂的猜测是,该功能是在库公共协议最终确定时添加的,没有人愿意冒险添加额外的功能。相反,他们决定利用已经存在的东西,而这个可怕的解决方案仍然存在。我很确定这个函数返回的值总是一样的。 @SergeyA 上帝,如果他们记录了这一点,那就太好了...... 您可能想问他们?有一些场地,我想? (抱歉,我不是 MSFT 开发人员) 【参考方案1】:

根据WSARecvMsg() documentation:

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

根据WSAIoctrl() documentation:

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

在大多数系统上,Microsoft 的提供程序是唯一安装的提供程序。但是,确实存在 3rd 方提供程序(自定义 TCP 堆栈等)并且也可能会安装。根据 WSADATAWSAStartup() 的文档:

Windows Sockets 的架构在版本 2 中进行了更改,以支持多个提供程序,并且 WSADATA 不再适用于单个供应商的堆栈。

进一步支持:

Windows Sockets 2 Architecture

Provider-Specific Extension Mechanism

当您使用socket() 创建套接字时,您无法控制使用哪个提供程序。当您改为使用WSASocket() 创建套接字时,您可以选择性地通过lpProtocolInfo 参数指定特定的提供程序。

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

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

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

一旦您检索到指向特定于供应商的函数的指针,只要提供程序保持加载在内存中(在第一次调用 WSAStartup() 和最后一次调用 @ 之间),您就可以尽可能多地重复使用该指针987654351@) 并传递一个属于该提供者的SOCKET

1:每Provider-Specific Extension Mechanism

在 Windows Vista 及更高版本上,新的 Winsock 系统扩展直接从 Winsock DLL 导出,因此不需要 WSAIoctl 函数来加载这些扩展。 Windows Vista 及更高版本上可用的新扩展函数包括从 Ws2_32.dll 导出的 WSAPollWSASendMsg 函数。

【讨论】:

该死,这是一个很好的答案,我希望我能再次投票。

以上是关于为啥 WSARecvMsg 函数实现为函数指针,这个指针可以重复使用吗?的主要内容,如果未能解决你的问题,请参考以下文章

为啥这两个函数指针在 C/C++ 中都是合法的?

当一个函数无返回值时,函数的类型应定义为啥

c++中为啥要用new 函数()实现多态?

为啥调用函数时指针会改变地址?

当函数返回时,指向超出范围的对象的 C++ 指针 - 为啥会这样?

为啥指向成员函数的指针不像数据指针那样只是内存地址