一些杂七杂八的测试代码就放这里了 做个索引记录
1 IOCP
从windows网络编程 第八章 获取的C语言版本代码
如果想学习 可以搜搜 “ 小猪 PIGGYXP iocp” “windows网络编程 iocp ” 应该有所收获
自己从头写了一遍c++ 以便加深记忆
#pragma once #include "WSAManager.h" #include "windows.h" #include <thread> #include <vector> const int defaultPortNum = 8893; const int defaultThreadNum = 1; #define CLOSEHANDLE(x) if(NULL != (x) && INVALID_HANDLE_VALUE != (x) ){CloseHandle(x);x = NULL;} #define CLOSESOCKET(x) if(INVALID_SOCKET != (x)){closesocket(x);x = INVALID_SOCKET;} const int defaultBufSize = 8192; typedef struct { OVERLAPPED Overlapped; WSABUF DataBuf; CHAR Buffer[defaultBufSize]; DWORD BytesSEND; DWORD BytesRECV; } PER_IO_OPERATION_DATA, *LPPER_IO_OPERATION_DATA; typedef struct { SOCKET Socket; } PER_HANDLE_DATA, *LPPER_HANDLE_DATA; class IOCPModel { public: IOCPModel(int portNum = defaultPortNum): completionPort_(NULL), threadNum_(defaultThreadNum), pthrArray_(NULL), listenSock_(INVALID_SOCKET), thrExitFlag_(true) { portNum_ = portNum; } ~IOCPModel() { StopThread(); CLOSEHANDLE(completionPort_); CLOSESOCKET(listenSock_); } bool Start(); bool Init(); bool ServerWorkerThread(void* CompletionPortID); bool StartThread(int thrNum = defaultThreadNum); bool StopThread(); bool ListenBindOrDie(); bool AcceptPostSocket(); void DeleteHandleData(PER_HANDLE_DATA* PerHandleData); void DeleteIoData(PER_IO_OPERATION_DATA* PerIoData); private: std::vector<PER_HANDLE_DATA*> perHandleDataVec_; std::vector<PER_IO_OPERATION_DATA*> perIOOperationDataVec_; WSAManager wsaManager_; HANDLE completionPort_; int portNum_; std::thread* pthrArray_; int threadNum_; bool thrExitFlag_; SOCKET listenSock_; };
#pragma once #include "IocpModel.h" #include <iomanip> bool IOCPModel::AcceptPostSocket() { SOCKET acceptSock; if ((acceptSock = WSAAccept(listenSock_, NULL, NULL, NULL, 0)) == SOCKET_ERROR) { std::cerr << "WSAAccept() failed with error " << WSAGetLastError() << std::endl; return false; } PER_HANDLE_DATA* pHandleData = new PER_HANDLE_DATA; if (NULL == pHandleData) { std::cerr << __FUNCTION__ << ". PER_HANDLE_DATA malloc failed" << std::endl; return false; } pHandleData->Socket = acceptSock; perHandleDataVec_.push_back(pHandleData); if ( CreateIoCompletionPort((HANDLE)acceptSock, completionPort_, (ULONG_PTR)pHandleData, 0) == NULL) { std::cerr << __FUNCTION__ << ". CreateIoCompletionPort failed" << std::endl; return false; } PER_IO_OPERATION_DATA* PerIoData = new PER_IO_OPERATION_DATA; if (NULL == PerIoData) { std::cerr << __FUNCTION__ << ". PER_IO_OPERATEION_DATA malloc failed" << std::endl; return false; } ZeroMemory(&(PerIoData->Overlapped), sizeof(OVERLAPPED)); PerIoData->BytesSEND = 0; PerIoData->BytesRECV = 0; PerIoData->DataBuf.len = defaultBufSize; PerIoData->DataBuf.buf = PerIoData->Buffer; perIOOperationDataVec_.push_back(PerIoData); DWORD Flags = 0; DWORD RecvBytes = 0; if (WSARecv(acceptSock, &(PerIoData->DataBuf), 1, &RecvBytes, &Flags, &(PerIoData->Overlapped), NULL) == SOCKET_ERROR) { if (WSAGetLastError() != ERROR_IO_PENDING) { std::cerr << __FUNCTION__ << ". WSARecv() failed with error " << WSAGetLastError() << std::endl; return false; } } return true; } bool IOCPModel::Start() { if (false == Init()) { return false; } while (true) { if (false == AcceptPostSocket()) break; } return true; } bool IOCPModel::StartThread(int thrNum ) { pthrArray_ = new std::thread[thrNum]; if (NULL == pthrArray_) { std::cerr << "new thread error" << std::endl; return false; } thrExitFlag_ = false; threadNum_ = thrNum; for (int i = 0; i < threadNum_; i++) { pthrArray_[i] = std::thread(&IOCPModel::ServerWorkerThread, this, completionPort_); } return true; } bool IOCPModel::StopThread() { thrExitFlag_ = true; for (int i = 0; i < threadNum_; i++) { pthrArray_[i].join(); } if (NULL != pthrArray_) { delete[] pthrArray_; } return true; } bool IOCPModel::ListenBindOrDie() { if ((listenSock_ = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED)) == INVALID_SOCKET) { std::cerr << __FUNCTION__ << ". Create listenSock_ failed "<< std::endl; return false; } SOCKADDR_IN InternetAddr; InternetAddr.sin_family = AF_INET; InternetAddr.sin_addr.s_addr = htonl(INADDR_ANY); InternetAddr.sin_port = htons(portNum_); if (bind(listenSock_, (PSOCKADDR)&InternetAddr, sizeof(InternetAddr)) == SOCKET_ERROR) { std::cerr << __FUNCTION__ << ". bind() failed with error " << WSAGetLastError() << std::endl; return false; } if (listen(listenSock_, 5) == SOCKET_ERROR) { std::cerr << __FUNCTION__ << ". listen() failed with error " << WSAGetLastError() << std::endl; return false; } return true; } bool IOCPModel::Init() { if ( (completionPort_ = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0) ) == NULL) { std::cerr << __FUNCTION__ << ". CreateIoCompletionPort failed with error: " << GetLastError() << std::endl; return false ; } if (false == StartThread(1)) { std::cerr << __FUNCTION__ << ". CreateIoCompletionPort failed with error: " << GetLastError() << std::endl; return false; } if (false == ListenBindOrDie()) { return false; } return true; } void IOCPModel::DeleteHandleData(PER_HANDLE_DATA* PerHandleData) { // todo delete PerHandleData; } void IOCPModel::DeleteIoData(PER_IO_OPERATION_DATA* PerIoData) { //todo delete PerIoData; } bool IOCPModel::ServerWorkerThread(void* completionPortID) { HANDLE CompletionPort = (HANDLE)completionPortID; DWORD BytesTransferred; //LPOVERLAPPED Overlapped; LPPER_HANDLE_DATA PerHandleData; LPPER_IO_OPERATION_DATA PerIoData; DWORD SendBytes, RecvBytes; DWORD Flags; while (!thrExitFlag_) { if (GetQueuedCompletionStatus(CompletionPort, &BytesTransferred, (LPDWORD)&PerHandleData, (LPOVERLAPPED *)&PerIoData, INFINITE) == 0) { std::cerr << __FUNCTION__ << ". GetQueuedCompletionStatus failed with error" << GetLastError() << std::endl; return false; } if (0 == BytesTransferred) { std::cerr << "close socket " << PerHandleData->Socket << std::endl; CLOSESOCKET(PerHandleData->Socket); DeleteHandleData(PerHandleData); DeleteIoData(PerIoData); continue; } // only for test { //再次投递 Flags = 0; ZeroMemory(&(PerIoData->Overlapped), sizeof(OVERLAPPED)); PerIoData->DataBuf.len = defaultBufSize; PerIoData->DataBuf.buf = PerIoData->Buffer; std::cout << std::setw(BytesTransferred) << PerIoData->DataBuf.buf << std::endl; if (WSARecv(PerHandleData->Socket, &(PerIoData->DataBuf), 1, &RecvBytes, &Flags, &(PerIoData->Overlapped), NULL) == SOCKET_ERROR) { if (WSAGetLastError() != ERROR_IO_PENDING) { printf("WSARecv() failed with error %d\n", WSAGetLastError()); return 0; } } } /* if (PerIoData->BytesRECV == 0) { PerIoData->BytesRECV = BytesTransferred; PerIoData->BytesSEND = 0; } else { PerIoData->BytesSEND += BytesTransferred; } if (PerIoData->BytesRECV > PerIoData->BytesSEND) { // Post another WSASend() request. // Since WSASend() is not gauranteed to send all of the bytes requested, // continue posting WSASend() calls until all received bytes are sent. ZeroMemory(&(PerIoData->Overlapped), sizeof(OVERLAPPED)); PerIoData->DataBuf.buf = PerIoData->Buffer + PerIoData->BytesSEND; PerIoData->DataBuf.len = PerIoData->BytesRECV - PerIoData->BytesSEND; if (WSASend(PerHandleData->Socket, &(PerIoData->DataBuf), 1, &SendBytes, 0, &(PerIoData->Overlapped), NULL) == SOCKET_ERROR) { if (WSAGetLastError() != ERROR_IO_PENDING) { printf("WSASend() failed with error %d\n", WSAGetLastError()); return 0; } } } else { PerIoData->BytesRECV = 0; // Now that there are no more bytes to send post another WSARecv() request. Flags = 0; ZeroMemory(&(PerIoData->Overlapped), sizeof(OVERLAPPED)); PerIoData->DataBuf.len = defaultBufSize; PerIoData->DataBuf.buf = PerIoData->Buffer; if (WSARecv(PerHandleData->Socket, &(PerIoData->DataBuf), 1, &RecvBytes, &Flags, &(PerIoData->Overlapped), NULL) == SOCKET_ERROR) { if (WSAGetLastError() != ERROR_IO_PENDING) { printf("WSARecv() failed with error %d\n", WSAGetLastError()); return 0; } } } */ } return true; }
// MyIocp.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include "IocpModel.h" int main() { IOCPModel iocpServer(8892); iocpServer.Start(); IOCPModel iocpServer_another; iocpServer_another.Start(); return 0; }
2 待续.......