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);
    

      

  • 相关阅读:
    linux---网络管理
    linux---Vim使用方法大全
    virtualenv离线创建虚拟环境
    python迭代器生成器进阶
    python函数对象
    Django等框架模板渲染中使用Vue控制数据
    django渲染模板与vue的语法冲突解决
    Linux网络抓包
    WSGI Server(uwsgi原理)
    python日志logging模块
  • 原文地址:https://www.cnblogs.com/seer/p/4513959.html
Copyright © 2011-2022 走看看