至此,主要的Winsock IO模型已经完成,个人不太喜欢select与WSAAsyncSelect, 所以没有给出示例。
以下代码仅为个人练手学习,参考资料:http://blog.csdn.net/wei801004/archive/2005/11/15/530147.aspx.
Server:
/***************************************************************************************************** * File name: WSACompletePort.cpp * Create time: 2011/04/17 * Module: View * Author: zengqh * Blog: http://blog.csdn.net/aimyton * --------------------------------------------------------------------------------------------------- * Memo: * *****************************************************************************************************/ #include <stdio.h> #include <stdlib.h> #include <WinSock2.h> #include <Windows.h> #pragma comment(lib, "WS2_32.lib") /***************************************************************************************************** * Macro and Struct definition *****************************************************************************************************/ #define trace printf #define MSGSIZE (50) typedef struct { WSAOVERLAPPED overlap; WSABUF Buffer; char szMessage[MSGSIZE]; DWORD NumberOfBytesRecvd; DWORD Flags; }PER_IO_OPERATION_DATA; /***************************************************************************************************** * Global variables *****************************************************************************************************/ /***************************************************************************************************** * Global function *****************************************************************************************************/ DWORD WINAPI RunTask(LPVOID lp); int main() { WSADATA wsa_data; SOCKET listen_socket; SOCKET accept_socket; int port = 27150; int ret_val; SOCKADDR_IN server_addr; HANDLE CompletePort; PER_IO_OPERATION_DATA per_operation_data; SYSTEM_INFO system_info; /* 1.Startup */ ret_val = WSAStartup(MAKEWORD(2, 2), &wsa_data); if(0 != ret_val) { trace("WSAStartup Error: %d/n", WSAGetLastError ()); return 1; } /* Complete port */ CompletePort = CreateIoCompletionPort( INVALID_HANDLE_VALUE, NULL, 0, 0); GetSystemInfo(&system_info); for(int loop = 0; loop < system_info.dwNumberOfProcessors; ++loop) { HANDLE handle = ::CreateThread( NULL, 0, RunTask, (LPVOID)CompletePort, 0, NULL); } /* 2.Create socket */ listen_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if(INVALID_SOCKET == listen_socket) { trace("socket Error: %d/n", WSAGetLastError ()); return 1; } /* 3.Bind */ server_addr.sin_family = AF_INET; server_addr.sin_port = htons(port); server_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); ret_val = bind(listen_socket, (SOCKADDR*)&server_addr, sizeof(server_addr)); if(SOCKET_ERROR == ret_val) { trace("bind Error: %d/n", WSAGetLastError ()); return 1; } /* 4.Listen */ ret_val = listen(listen_socket, 5); if(SOCKET_ERROR == ret_val) { trace("listen Error: %d/n", WSAGetLastError ()); return 1; } for(;;) { accept_socket = accept(listen_socket, NULL, NULL); if(INVALID_SOCKET == accept_socket) { trace("accept Error: %d/n", WSAGetLastError()); break; } CreateIoCompletionPort( (HANDLE)accept_socket, CompletePort, (ULONG_PTR)accept_socket, 0); memset(&per_operation_data, 0, sizeof(per_operation_data)); per_operation_data.Buffer.buf = per_operation_data.szMessage; per_operation_data.Buffer.len = MSGSIZE; /* First recv */ ret_val = WSARecv( accept_socket, &per_operation_data.Buffer, 1, &per_operation_data.NumberOfBytesRecvd, &per_operation_data.Flags, &per_operation_data.overlap, NULL); if (SOCKET_ERROR == ret_val && ERROR_IO_PENDING != WSAGetLastError()) { trace("WSARecv in main Error %d/n", WSAGetLastError()); } } CloseHandle(CompletePort); closesocket(listen_socket); WSACleanup(); system("pause"); return 0; } DWORD WINAPI RunTask(LPVOID lp) { HANDLE CompletionPort = (HANDLE)lp; DWORD BytesTransferred; PER_IO_OPERATION_DATA* lp_per_operation_data; SOCKET client_socket; int ret_val; for(;;) { ret_val = GetQueuedCompletionStatus( CompletionPort, &BytesTransferred, (LPDWORD)&client_socket, (LPOVERLAPPED*)&lp_per_operation_data, WSA_INFINITE); if(0 == ret_val) { trace("GetQueuedCompletionStatus Error: %d/n", WSAGetLastError()); return 1; } if(0 != BytesTransferred) { trace("%s/n", lp_per_operation_data->Buffer.buf); } memset(lp_per_operation_data, 0, sizeof(PER_IO_OPERATION_DATA)); lp_per_operation_data->Buffer.buf = lp_per_operation_data->szMessage; lp_per_operation_data->Buffer.len = MSGSIZE; /* Next recv */ ret_val = WSARecv( client_socket, &lp_per_operation_data->Buffer, 1, &lp_per_operation_data->NumberOfBytesRecvd, &lp_per_operation_data->Flags, &lp_per_operation_data->overlap, NULL); if (SOCKET_ERROR == ret_val && ERROR_IO_PENDING != WSAGetLastError()) { trace("WSARecv in task Error %d/n", WSAGetLastError()); } } } /***************************************************************************************************** * Class declare ******************************************************************************************************/ /***************************************************************************************************** * Class definition *****************************************************************************************************/ /***********************************End of File*******************************************************/
客户端还是如此:
/***************************************************************************************************** * File name: Send.cpp * Create time: 2011/04/12 * Module: View * Author: zengqh * Blog: http://blog.csdn.net/aimyton * --------------------------------------------------------------------------------------------------- * Memo: * *****************************************************************************************************/ #include <stdio.h> #include <stdlib.h> #include <Windows.h> #pragma comment(lib, "WS2_32.lib") /***************************************************************************************************** * Macro and Struct definition *****************************************************************************************************/ #define trace printf /***************************************************************************************************** * Global variables *****************************************************************************************************/ /***************************************************************************************************** * Global function *****************************************************************************************************/ int main() { WSADATA wsa_data; SOCKET s; SOCKADDR_IN server_addr; int port = 27150; int ret_val; char send_buffer[50] = {0}; static int send_index = 0; /* 1.Startup */ ret_val = WSAStartup(MAKEWORD(2, 2), &wsa_data); if(0 != ret_val) { trace("WSAStartup Error: %d/n", WSAGetLastError ()); return 1; } s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if(INVALID_SOCKET == s) { trace("socket Error: %d/n", WSAGetLastError ()); return 1; } server_addr.sin_family = AF_INET; server_addr.sin_port = htons(port); server_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); ret_val = connect(s, (SOCKADDR*)&server_addr, sizeof(server_addr)); if(SOCKET_ERROR == ret_val) { trace("connect Error: %d/n", WSAGetLastError ()); return 1; } int send_bytes = 0; for(;;) { sprintf(send_buffer, "Send, %d", send_index++); send_bytes = send(s, send_buffer, sizeof(send_buffer), 0); printf("Client send: %s/n", send_buffer); Sleep(10); if(send_index >= 100) { //break; } } closesocket(s); WSACleanup(); } /***************************************************************************************************** * Class declare ******************************************************************************************************/ /***************************************************************************************************** * Class definition *****************************************************************************************************/ /***********************************End of File*******************************************************/