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

  

你可能感兴趣的:(connect)