标签:事件通知 heapalloc memset bind and 端点 soc .net iss
转载请注明来源:http://blog.csdn.net/caoshiying?viewmode=contents
HANDLE WINAPI CreateIoCompletionPort( _In_ HANDLE FileHandle, _In_opt_ HANDLE ExistingCompletionPort, _In_ ULONG_PTR CompletionKey, _In_ DWORD NumberOfConcurrentThreads );
BOOL WINAPI GetQueuedCompletionStatus( _In_ HANDLE CompletionPort, _Out_ LPDWORD lpNumberOfBytes, _Out_ PULONG_PTR lpCompletionKey, _Out_ LPOVERLAPPED *lpOverlapped, _In_ DWORD dwMilliseconds );
Windows Server 2003和Windows XP:关闭完成端口句柄,调用优秀不会导致之前的行为。该函数将继续等待直到一项是从港口或直到发生超时删除,如果指定以外的无限价值。
如果GetQueuedCompletionStatus函数调用成功,它出列完成包一个成功的I/O操作完成端口和存储信息的变量所指向的下列参数:lpNumberOfBytes,lpcompletionkey,和lpOverlapped。在失败(返回值是错误的),这些相同的参数可以包含特定的值组合如下:BOOL WINAPI PostQueuedCompletionStatus( _In_ HANDLE CompletionPort, _In_ DWORD dwNumberOfBytesTransferred, _In_ ULONG_PTR dwCompletionKey, _In_opt_ LPOVERLAPPED lpOverlapped );
#pragma once #define SOCKET_MESSAGE_SIZE 1024 #include <WinSock2.h> #include <common_callback.h> typedef enum { RECV_POSTED }OPERATION_TYPE; typedef struct { WSAOVERLAPPED overlap; WSABUF buffer; char message[SOCKET_MESSAGE_SIZE]; DWORD received_count; DWORD flags; OPERATION_TYPE operation_type; }PEERIO_OPERATION_DATA, *LPPEERIO_OPERATION_DATA; class completeio_server_manager: public iserver_manager { private: int iport; int iaddr_size; common_callback callback; BOOL brunning; SOCKET server; WSADATA wsaData; HANDLE hcomplete_port; SYSTEM_INFO system_info; LPPEERIO_OPERATION_DATA peer_data; bool bdisposed; protected: bool accept_by_crt(); bool accept_by_winapi(); public: void receive(); void shutdown(); void start_receive(); void start_accept(); public: completeio_server_manager(); virtual ~completeio_server_manager(); };
#include "completeio_server_manager.h" #include <stdio.h> #include <tchar.h> completeio_server_manager::completeio_server_manager() { iport = 5150; iaddr_size = sizeof(SOCKADDR_IN); brunning = FALSE; GetSystemInfo(&system_info); callback.set_manager(this); callback.set_receive_thread_coount(system_info.dwNumberOfProcessors); hcomplete_port = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0); bdisposed = false; } completeio_server_manager::~completeio_server_manager() { if (bdisposed) shutdown(); } bool completeio_server_manager::accept_by_crt() { return true; } bool completeio_server_manager::accept_by_winapi() { SOCKADDR_IN server_addr; SOCKADDR_IN client_addr; SOCKET client; LPPEERIO_OPERATION_DATA peer_data; int iresult = -1; WSAStartup(MAKEWORD(2, 2), &wsaData); server = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); server_addr.sin_addr.S_un.S_addr = htonl(INADDR_ANY); server_addr.sin_family = AF_INET; server_addr.sin_port = htons(iport); do { iresult = bind(server, (struct sockaddr*)&server_addr, iaddr_size); if (iresult == SOCKET_ERROR) { iport++; server_addr.sin_port = htons(iport); } } while (iresult == -1); listen(server, 3); printf("基于完成端口模型的Socket服务器启动成功。监听端口是:%d\n", iport); while (brunning) { printf("开始监听请求。\n"); client = accept(server, (struct sockaddr*)&client_addr, &iaddr_size); if (client == SOCKET_ERROR) continue; printf("新客户端连接:%s:%d\n", inet_ntoa(client_addr.sin_addr), htons(client_addr.sin_port)); CreateIoCompletionPort((HANDLE)client, hcomplete_port, (DWORD)client, 0); peer_data = (LPPEERIO_OPERATION_DATA)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PEERIO_OPERATION_DATA)); peer_data->buffer.len = SOCKET_MESSAGE_SIZE; peer_data->buffer.buf = peer_data->message; peer_data->operation_type = RECV_POSTED; printf("开始接收客户端传送数据。\n"); WSARecv(client, &peer_data->buffer, 1, &peer_data->received_count, &peer_data->flags, &peer_data->overlap, NULL); printf("收到客户端数据。\n"); } return true; } void completeio_server_manager::receive() { DWORD dwtransfered = 0; SOCKET client; LPPEERIO_OPERATION_DATA peer = nullptr; while (brunning) { printf("线程:%d,查询端口状态信息。\n",GetCurrentThreadId()); GetQueuedCompletionStatus(hcomplete_port, &dwtransfered, (PULONG_PTR)&client, (LPOVERLAPPED*)&peer, INFINITE); printf("获得端口信息。\n"); if (dwtransfered == 0xFFFFFFFF) return; if (peer->operation_type == RECV_POSTED) { if (dwtransfered == 0) { closesocket(client); printf("有客户端退出了。\n"); HeapFree(GetProcessHeap(), 0, peer); } else { peer->message[dwtransfered] = 0; send(client, peer->message, dwtransfered, 0); memset(peer, 0, sizeof(PEERIO_OPERATION_DATA)); peer->buffer.len = SOCKET_MESSAGE_SIZE; peer->buffer.buf = peer->message; peer->operation_type = RECV_POSTED; WSARecv(client, &peer->buffer, 1, &peer->received_count, &peer->flags, &peer->overlap, nullptr); } } } } void completeio_server_manager::shutdown() { PostQueuedCompletionStatus(hcomplete_port, 0xFFFFFFFF, 0, NULL);//端口尾随数据。 brunning = FALSE; callback.shutdown();//清扫 CloseHandle(hcomplete_port); closesocket(server); WSACleanup(); bdisposed = true; } void completeio_server_manager::start_accept() { brunning = TRUE; bdisposed = false; callback.start_accept_by_winapi(); } void completeio_server_manager::start_receive() { brunning = TRUE; bdisposed = false; callback.start_receive(); } int main() { completeio_server_manager csm; csm.start_accept(); csm.start_receive(); printf("服务器启动成功。按任意键关闭服务器并退出程序。\n"); getchar(); csm.shutdown(); return 0; }
标签:事件通知 heapalloc memset bind and 端点 soc .net iss
原文地址:http://blog.csdn.net/caoshiying/article/details/52904031