zoukankan      html  css  js  c++  java
  • 使用WSAIoctl获取AcceptEx,Connectex,Getacceptexsockaddrs函数指针

    运行WinNT和Win2000的系统上,这些APIs在Microsoft提供的DLL(mswsock.dll)里实现,可以通过链接mswsock.lib或者通过WSAioctl的SIO_GET_EXTENSION_FUNCTION_POINTER操作动态调用这些扩展APIs.

    未获取函数指针就调用函数(如直接连接mswsock.lib并直接调用AcceptEx)的消耗是很大的,因为AcceptEx 实际上是存在于Winsock2结构体系之外的。每次应用程序常试在服务提供层上(mswsock之上)调用AcceptEx时,都要先通过WSAIoctl获取该函数指针。如果要避免这个很影响性能的操作,应用程序最好是直接从服务提供层通过WSAIoctl先获取这些APIs的指针。

    需要注意的是,通过WSAIoctl获取AcceptEx函数指针时,只需要传递给WSAIoctl一个有效的SOCKET即可,该Socket的类型不会影响获取的AcceptEx函数指针。

    同理可以获取Connectex与GetAcceptExSockaddrs函数指针。

    代码如下:

    typedef BOOL (WINAPI *AcceptExPtr)(SOCKET, SOCKET, PVOID, DWORD, DWORD, DWORD, LPDWORD, LPOVERLAPPED);
    typedef BOOL (WINAPI *ConnectExPtr)(SOCKET, const struct sockaddr *, int, PVOID, DWORD, LPDWORD, LPOVERLAPPED);
    typedef void (WINAPI *GetAcceptExSockaddrsPtr)(PVOID, DWORD, DWORD, DWORD, LPSOCKADDR *, LPINT, LPSOCKADDR *, LPINT);
    
    
    struct win32_extension_fns {
    	AcceptExPtr AcceptEx;
    	ConnectExPtr ConnectEx;
    	GetAcceptExSockaddrsPtr GetAcceptExSockaddrs;
    };
    
    
    #ifndef WSAID_ACCEPTEX
    #define WSAID_ACCEPTEX 
    	{0xb5367df1,0xcbac,0x11cf,{0x95,0xca,0x00,0x80,0x5f,0x48,0xa1,0x92}}
    #endif
    #ifndef WSAID_CONNECTEX
    #define WSAID_CONNECTEX 
    	{0x25a207b9,0xddf3,0x4660,{0x8e,0xe9,0x76,0xe5,0x8c,0x74,0x06,0x3e}}
    #endif
    #ifndef WSAID_GETACCEPTEXSOCKADDRS
    #define WSAID_GETACCEPTEXSOCKADDRS 
    	{0xb5367df2,0xcbac,0x11cf,{0x95,0xca,0x00,0x80,0x5f,0x48,0xa1,0x92}}
    #endif
    
    
    
    
    void * get_extension_function(SOCKET s, const GUID *which_fn)
    {
    	void *ptr = NULL;
    	DWORD bytes=0;
    	WSAIoctl(s, SIO_GET_EXTENSION_FUNCTION_POINTER,
    	    (GUID*)which_fn, sizeof(*which_fn),
    	    &ptr, sizeof(ptr),
    	    &bytes, NULL, NULL);
    
    	return ptr;
    }
    

      调用:

    const GUID acceptex = WSAID_ACCEPTEX;
    	const GUID connectex = WSAID_CONNECTEX;
    	const GUID getacceptexsockaddrs = WSAID_GETACCEPTEXSOCKADDRS;
    	SOCKET s = socket(AF_INET, SOCK_STREAM, 0);
    	if (s == INVALID_SOCKET)
    		return;
    	ext->AcceptEx = (AcceptExPtr)get_extension_function(s, &acceptex);
    	ext->ConnectEx = (ConnectExPtr)get_extension_function(s, &connectex);
    	ext->GetAcceptExSockaddrs = (GetAcceptExSockaddrsPtr)get_extension_function(s,&getacceptexsockaddrs);
    	closesocket(s);
    

      

  • 相关阅读:
    Educational Codeforces Round 95(A-C题解)
    Codeforces Round #669 (Div. 2)A-C题解
    Codeforces Round #668 (Div. 2)A-C题解
    八月第四周总结
    牛客小白月赛27部分题解
    八月第三周总结
    Codeforces Round #665 (Div. 2)A-C题解
    Kubernetes K8S之存储ConfigMap详解
    在Linux下如何根据域名自签发OpenSSL证书与常用证书转换
    Linux系统如何在离线环境或内网环境安装部署Docker服务和其他服务
  • 原文地址:https://www.cnblogs.com/seer/p/4513959.html
Copyright © 2011-2022 走看看