Windows网络编程:使用Completion Port
下面是使用Completion Port的一个简单的例子:
#include
<
winsock2.h
>
#include < windows.h >
#include < stdio.h >
#pragma comment(lib, " ws2_32.lib " )
#define LISTEN_PORT 5080
#define DATA_BUFSIZE 512
typedef struct
{
WSAOVERLAPPED wsaOverlapped;
WSABUF wsaBuf;
char buffer[DATA_BUFSIZE];
}PER_IO_OPERATION_DATA, * LPPER_IO_OPERATION_DATA;
typedef struct
{
SOCKET sock;
}PER_HANDLE_DATA, * LPPER_HANDLE_DATA;
DWORD WINAPI ServerWorkerThread(LPVOID lpCompletionPortID);
int main()
{
WSADATA wsaData;
int nRet;
HANDLE hCompletionPort;
SYSTEM_INFO systemInfo;
int i;
HANDLE hThread;
DWORD dwThreadID;
SOCKET sockListen;
SOCKADDR_IN listenAddr;
SOCKET acceptSock;
LPPER_HANDLE_DATA perHandleData;
LPPER_IO_OPERATION_DATA lpPerIoOperationData;
DWORD dwFlags;
DWORD dwBytesRecv;
nRet = WSAStartup(MAKEWORD( 2 , 2 ), & wsaData);
if (nRet != 0 )
{
printf( " WSAStartup() failed error:%d\n " , nRet);
return 1 ;
}
else
printf( " WSAStartup is OK!\n " );
if ((hCompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0 , 0 )) == NULL)
{
printf( " CreateIoCompletionPort() failed with error %d.\n " , GetLastError());
WSACleanup();
return 1 ;
}
else
{
printf( " CreateIoCompletionPort() is OK.\n " );
}
GetSystemInfo( & systemInfo);
for (i = 0 ; i < ( int )systemInfo.dwNumberOfProcessors * 2 ; ++ i)
{
if ((hThread = CreateThread(NULL, 0 , ServerWorkerThread, hCompletionPort, 0 , & dwThreadID)) == NULL)
{
printf( " CreateThread() failed with error %d.\n " , GetLastError());
WSACleanup();
return 1 ;
}
else
printf( " CreateThread() is OK! Thread ID:%d\n " , dwThreadID);
CloseHandle(hThread);
}
if ((sockListen = WSASocket(AF_INET, SOCK_STREAM, 0 , NULL, 0 , WSA_FLAG_OVERLAPPED)) == INVALID_SOCKET)
{
printf( " WSASocket() failed with error %d.\n " , WSAGetLastError());
WSACleanup();
return 1 ;
}
else
{
printf( " WSASocket() is OK!\n " );
}
listenAddr.sin_family = AF_INET;
listenAddr.sin_addr.s_addr = htonl(INADDR_ANY);
listenAddr.sin_port = htons(LISTEN_PORT);
if (bind(sockListen, (SOCKADDR * ) & listenAddr, sizeof (listenAddr)) == SOCKET_ERROR)
{
printf( " bind() failed, error:%d.\n " , WSAGetLastError());
closesocket(sockListen);
WSACleanup();
return 1 ;
}
else
printf( " bind()is fine!\n " );
if (listen(sockListen, 5 ) == SOCKET_ERROR)
{
printf( " listen() failed, error:%d.\n " , WSAGetLastError());
closesocket(sockListen);
WSACleanup();
return 1 ;
}
else
{
printf( " listen() is OK! " );
}
while (TRUE)
{
if ((acceptSock = WSAAccept(sockListen, NULL, NULL, NULL, 0 )) == SOCKET_ERROR)
{
printf( " WSAAccept() failed, error:%d.\n " , WSAGetLastError());
WSACleanup();
return 1 ;
}
else
{
printf( " WSAAccept() is OK!.\n " );
}
if ((perHandleData = (LPPER_HANDLE_DATA)GlobalAlloc(GPTR, sizeof (PER_HANDLE_DATA))) == NULL)
{
printf( " GlobalAlloc() failed, error:%d.\n " , GetLastError());
WSACleanup();
return 1 ;
}
else
{
printf( " GlobalAlloc() for PER_HANDLE_DATA is OK!.\n " );
}
printf( " socket %d create.\n " , acceptSock);
perHandleData -> sock = acceptSock;
if (CreateIoCompletionPort((HANDLE)acceptSock, hCompletionPort, (DWORD)perHandleData, 0 ) == NULL)
{
printf( " CreateIoCompletionPort() failed, error:%d.\n " , GetLastError());
return 1 ;
}
else
{
printf( " CreateIoCompletionPort() is OK!.\n " );
}
if ((lpPerIoOperationData = (LPPER_IO_OPERATION_DATA)GlobalAlloc(GPTR, sizeof (PER_IO_OPERATION_DATA))) == NULL)
{
printf( " GlobalAlloc() failed, error:%d.\n " , GetLastError());
return 1 ;
}
else
{
printf( " GlobalAlloc() for PER_IO_OPERATION_DATA is OK!\n " );
}
ZeroMemory( & (lpPerIoOperationData -> wsaOverlapped), sizeof (OVERLAPPED));
lpPerIoOperationData -> wsaBuf.len = DATA_BUFSIZE;
lpPerIoOperationData -> wsaBuf.buf = lpPerIoOperationData -> buffer;
dwFlags = 0 ;
if (WSARecv(acceptSock, & (lpPerIoOperationData -> wsaBuf), 1 , & dwBytesRecv, & dwFlags, & (lpPerIoOperationData -> wsaOverlapped), NULL) == SOCKET_ERROR)
{
if (WSAGetLastError() != ERROR_IO_PENDING)
{
printf( " WSARecv() failed, error %d\n " , WSAGetLastError());
WSACleanup();
return 1 ;
}
}
else
{
printf( " WSARecv() is OK!\n " );
}
}
if (WSACleanup() == SOCKET_ERROR)
{
printf( " WSACleanup() failed, error:%d.\n " , WSAGetLastError());
}
else
{
printf( " WSACleanup() is OK!.\n " );
}
}
DWORD WINAPI ServerWorkerThread(LPVOID lpCompletionPortID)
{
HANDLE hCompletionPort = (HANDLE)lpCompletionPortID;
DWORD dwBytesTransferred = 0 ;
LPPER_HANDLE_DATA lpPerHandleData;
LPPER_IO_OPERATION_DATA lpPerIoData;
DWORD dwFlags;
while (TRUE)
{
if (GetQueuedCompletionStatus(hCompletionPort, & dwBytesTransferred,
(DWORD * ) & lpPerHandleData, (LPOVERLAPPED * ) & lpPerIoData, INFINITE) == 0 )
{
printf( " GetQueuedCompletionStatus() failed, error:%d.\n " , GetLastError());
return 0 ;
}
else
{
printf( " GetQueuedCompletionStatus() is OK!.\n " );
}
if (dwBytesTransferred == 0 )
{
printf( " closing socket %d.\n " , lpPerHandleData);
if (closesocket(lpPerHandleData -> sock) == SOCKET_ERROR)
{
printf( " closesocket() failed with error %d\n " , WSAGetLastError());
return 0 ;
}
else
printf( " closesocket() is fine!\n " );
GlobalFree(lpPerHandleData);
GlobalFree(lpPerIoData);
continue ;
}
else
{
printf( " %s " , lpPerIoData -> buffer);
ZeroMemory( & (lpPerIoData -> wsaOverlapped), sizeof (OVERLAPPED));
lpPerIoData -> wsaBuf.len = DATA_BUFSIZE;
lpPerIoData -> wsaBuf.buf = lpPerIoData -> buffer;
dwFlags = 0 ;
if (WSARecv(lpPerHandleData -> sock, & (lpPerIoData -> wsaBuf), 1 , & dwBytesTransferred, & dwFlags, & (lpPerIoData -> wsaOverlapped), NULL) == SOCKET_ERROR)
{
if (WSAGetLastError() != ERROR_IO_PENDING)
{
printf( " WSARecv() failed, error %d\n " , WSAGetLastError());
return 1 ;
}
}
else
{
printf( " WSARecv() is OK!\n " );
}
}
}
}
#include < windows.h >
#include < stdio.h >
#pragma comment(lib, " ws2_32.lib " )
#define LISTEN_PORT 5080
#define DATA_BUFSIZE 512
typedef struct
{
WSAOVERLAPPED wsaOverlapped;
WSABUF wsaBuf;
char buffer[DATA_BUFSIZE];
}PER_IO_OPERATION_DATA, * LPPER_IO_OPERATION_DATA;
typedef struct
{
SOCKET sock;
}PER_HANDLE_DATA, * LPPER_HANDLE_DATA;
DWORD WINAPI ServerWorkerThread(LPVOID lpCompletionPortID);
int main()
{
WSADATA wsaData;
int nRet;
HANDLE hCompletionPort;
SYSTEM_INFO systemInfo;
int i;
HANDLE hThread;
DWORD dwThreadID;
SOCKET sockListen;
SOCKADDR_IN listenAddr;
SOCKET acceptSock;
LPPER_HANDLE_DATA perHandleData;
LPPER_IO_OPERATION_DATA lpPerIoOperationData;
DWORD dwFlags;
DWORD dwBytesRecv;
nRet = WSAStartup(MAKEWORD( 2 , 2 ), & wsaData);
if (nRet != 0 )
{
printf( " WSAStartup() failed error:%d\n " , nRet);
return 1 ;
}
else
printf( " WSAStartup is OK!\n " );
if ((hCompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0 , 0 )) == NULL)
{
printf( " CreateIoCompletionPort() failed with error %d.\n " , GetLastError());
WSACleanup();
return 1 ;
}
else
{
printf( " CreateIoCompletionPort() is OK.\n " );
}
GetSystemInfo( & systemInfo);
for (i = 0 ; i < ( int )systemInfo.dwNumberOfProcessors * 2 ; ++ i)
{
if ((hThread = CreateThread(NULL, 0 , ServerWorkerThread, hCompletionPort, 0 , & dwThreadID)) == NULL)
{
printf( " CreateThread() failed with error %d.\n " , GetLastError());
WSACleanup();
return 1 ;
}
else
printf( " CreateThread() is OK! Thread ID:%d\n " , dwThreadID);
CloseHandle(hThread);
}
if ((sockListen = WSASocket(AF_INET, SOCK_STREAM, 0 , NULL, 0 , WSA_FLAG_OVERLAPPED)) == INVALID_SOCKET)
{
printf( " WSASocket() failed with error %d.\n " , WSAGetLastError());
WSACleanup();
return 1 ;
}
else
{
printf( " WSASocket() is OK!\n " );
}
listenAddr.sin_family = AF_INET;
listenAddr.sin_addr.s_addr = htonl(INADDR_ANY);
listenAddr.sin_port = htons(LISTEN_PORT);
if (bind(sockListen, (SOCKADDR * ) & listenAddr, sizeof (listenAddr)) == SOCKET_ERROR)
{
printf( " bind() failed, error:%d.\n " , WSAGetLastError());
closesocket(sockListen);
WSACleanup();
return 1 ;
}
else
printf( " bind()is fine!\n " );
if (listen(sockListen, 5 ) == SOCKET_ERROR)
{
printf( " listen() failed, error:%d.\n " , WSAGetLastError());
closesocket(sockListen);
WSACleanup();
return 1 ;
}
else
{
printf( " listen() is OK! " );
}
while (TRUE)
{
if ((acceptSock = WSAAccept(sockListen, NULL, NULL, NULL, 0 )) == SOCKET_ERROR)
{
printf( " WSAAccept() failed, error:%d.\n " , WSAGetLastError());
WSACleanup();
return 1 ;
}
else
{
printf( " WSAAccept() is OK!.\n " );
}
if ((perHandleData = (LPPER_HANDLE_DATA)GlobalAlloc(GPTR, sizeof (PER_HANDLE_DATA))) == NULL)
{
printf( " GlobalAlloc() failed, error:%d.\n " , GetLastError());
WSACleanup();
return 1 ;
}
else
{
printf( " GlobalAlloc() for PER_HANDLE_DATA is OK!.\n " );
}
printf( " socket %d create.\n " , acceptSock);
perHandleData -> sock = acceptSock;
if (CreateIoCompletionPort((HANDLE)acceptSock, hCompletionPort, (DWORD)perHandleData, 0 ) == NULL)
{
printf( " CreateIoCompletionPort() failed, error:%d.\n " , GetLastError());
return 1 ;
}
else
{
printf( " CreateIoCompletionPort() is OK!.\n " );
}
if ((lpPerIoOperationData = (LPPER_IO_OPERATION_DATA)GlobalAlloc(GPTR, sizeof (PER_IO_OPERATION_DATA))) == NULL)
{
printf( " GlobalAlloc() failed, error:%d.\n " , GetLastError());
return 1 ;
}
else
{
printf( " GlobalAlloc() for PER_IO_OPERATION_DATA is OK!\n " );
}
ZeroMemory( & (lpPerIoOperationData -> wsaOverlapped), sizeof (OVERLAPPED));
lpPerIoOperationData -> wsaBuf.len = DATA_BUFSIZE;
lpPerIoOperationData -> wsaBuf.buf = lpPerIoOperationData -> buffer;
dwFlags = 0 ;
if (WSARecv(acceptSock, & (lpPerIoOperationData -> wsaBuf), 1 , & dwBytesRecv, & dwFlags, & (lpPerIoOperationData -> wsaOverlapped), NULL) == SOCKET_ERROR)
{
if (WSAGetLastError() != ERROR_IO_PENDING)
{
printf( " WSARecv() failed, error %d\n " , WSAGetLastError());
WSACleanup();
return 1 ;
}
}
else
{
printf( " WSARecv() is OK!\n " );
}
}
if (WSACleanup() == SOCKET_ERROR)
{
printf( " WSACleanup() failed, error:%d.\n " , WSAGetLastError());
}
else
{
printf( " WSACleanup() is OK!.\n " );
}
}
DWORD WINAPI ServerWorkerThread(LPVOID lpCompletionPortID)
{
HANDLE hCompletionPort = (HANDLE)lpCompletionPortID;
DWORD dwBytesTransferred = 0 ;
LPPER_HANDLE_DATA lpPerHandleData;
LPPER_IO_OPERATION_DATA lpPerIoData;
DWORD dwFlags;
while (TRUE)
{
if (GetQueuedCompletionStatus(hCompletionPort, & dwBytesTransferred,
(DWORD * ) & lpPerHandleData, (LPOVERLAPPED * ) & lpPerIoData, INFINITE) == 0 )
{
printf( " GetQueuedCompletionStatus() failed, error:%d.\n " , GetLastError());
return 0 ;
}
else
{
printf( " GetQueuedCompletionStatus() is OK!.\n " );
}
if (dwBytesTransferred == 0 )
{
printf( " closing socket %d.\n " , lpPerHandleData);
if (closesocket(lpPerHandleData -> sock) == SOCKET_ERROR)
{
printf( " closesocket() failed with error %d\n " , WSAGetLastError());
return 0 ;
}
else
printf( " closesocket() is fine!\n " );
GlobalFree(lpPerHandleData);
GlobalFree(lpPerIoData);
continue ;
}
else
{
printf( " %s " , lpPerIoData -> buffer);
ZeroMemory( & (lpPerIoData -> wsaOverlapped), sizeof (OVERLAPPED));
lpPerIoData -> wsaBuf.len = DATA_BUFSIZE;
lpPerIoData -> wsaBuf.buf = lpPerIoData -> buffer;
dwFlags = 0 ;
if (WSARecv(lpPerHandleData -> sock, & (lpPerIoData -> wsaBuf), 1 , & dwBytesTransferred, & dwFlags, & (lpPerIoData -> wsaOverlapped), NULL) == SOCKET_ERROR)
{
if (WSAGetLastError() != ERROR_IO_PENDING)
{
printf( " WSARecv() failed, error %d\n " , WSAGetLastError());
return 1 ;
}
}
else
{
printf( " WSARecv() is OK!\n " );
}
}
}
}