最近csdn 多了几个iocp 教程,花了两天时间,昨天到半夜,今天终于调试通过,注意只是让程序通过。
比较简单,欢迎新手,结合网上出现的icop 模型,补充学习。
#include "Socket.h" #include <iostream> #include <string> #include <boost/thread.hpp> #include <boost/bind.hpp> #include "HtmlHelper.h" #include "UrlQueue.h" #include <winsock2.h> #include <windows.h>A #include <tchar.h> using namespace boost; using namespace std; #define MyQueue UrlQueue::GetInstance() #define DATA_BUFSIZE 134096 // 接收缓冲区大小 #define BUFFER_SIZE 134096 // 接收缓冲区大小 typedef struct //这个玩意就是灌数据,取数据的一个自定义数据结构 //和那个wm_data差不了多少,不过就是老要塞一个OverLapped结构, { OVERLAPPED Overlapped; WSABUF DataBuf; CHAR Buffer[DATA_BUFSIZE]; int nOperationType; // 操作类型 #define OP_READ 1 } PER_IO_OPERATION_DATA, * LPPER_IO_OPERATION_DATA; typedef struct { SOCKET Socket; } PER_HANDLE_DATA, * LPPER_HANDLE_DATA; Socket::Socket(const std::string& host, int port) { //m_SocketId = -1; WSADATA info; if (WSAStartup(MAKEWORD(2,0), &info)) { throw "Could not start WSA"; } NewSocket(host,port); } bool Socket::NewSocket(const std::string& host, int port) { m_socket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); //创建客户端套接字 if( m_socket ==INVALID_SOCKET){ printf("创建套接字失败!"); return false; } // 创建完成端口 // threads. m_hCompletionPort = CreateIoCompletionPort( INVALID_HANDLE_VALUE, NULL, 0, 0 ); if ( m_hCompletionPort == NULL ) { closesocket(m_socket ); return FALSE; } hostent *he; if ((he = gethostbyname((char*)host.c_str())) == 0) { error = strerror(errno); throw error; cout<<"连接失败"; } sockaddr_in addr; addr.sin_family = AF_INET; addr.sin_port = htons(port); // addr.sin_addr.S_un.S_addr = ip; addr.sin_addr = *((in_addr *)he->h_addr); memset(&(addr.sin_zero), 0, 8); if (-1 == connect(m_socket, (sockaddr *) &addr, sizeof(sockaddr))) { error = strerror(WSAGetLastError()); throw error; cout<<"连接失败"; } } void Socket::End() { WSACleanup(); } Socket::~Socket() { Close(); End(); } void Socket::Close() { //closesocket(m_socket); } void Socket::SendLine(std::string s) { s += '\n'; send(m_socket,s.c_str(),s.length(),0); } void Socket::DownloadBody(const std::string& sendData, std::string & recvData) { SendLine(sendData); boost::function0 <void> f = boost::bind(&Socket::ClientThread,this,m_hCompletionPort); boost::thread thrd(f); LPPER_HANDLE_DATA PerHandleData; if ((PerHandleData = (LPPER_HANDLE_DATA) GlobalAlloc(GPTR, sizeof(PER_HANDLE_DATA))) == NULL) { printf("GlobalAlloc() failed with error %d/n", GetLastError()); } PerHandleData->Socket = m_socket; HANDLE h = CreateIoCompletionPort((HANDLE) m_socket, m_hCompletionPort, (DWORD) PerHandleData, 0); LPPER_IO_OPERATION_DATA PerIoData; //清管子的数据结构,准备往里面灌数据 // if ((PerIoData = (LPPER_IO_OPERATION_DATA) GlobalAlloc(GPTR,sizeof(PER_IO_OPERATION_DATA))) == NULL) { printf("GlobalAlloc() failed with error %d/n", GetLastError()); // return ; } ZeroMemory(&(PerIoData->Overlapped), sizeof(OVERLAPPED)); // PerIoData->BytesRECV = 0; PerIoData->DataBuf.len = DATA_BUFSIZE; PerIoData->DataBuf.buf = PerIoData->Buffer; PerIoData->nOperationType = OP_READ; // PerIoData->activeSocket = m_socket; Flags = 0; DWORD RecvBytes; if (WSARecv(m_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 1; } } } int Socket::ClientThread(HANDLE fdf) { DWORD BytesTransferred; LPOVERLAPPED Overlapped; LPPER_HANDLE_DATA PerHandleData; LPPER_IO_OPERATION_DATA PerIoData; DWORD RecvBytes; DWORD Flags; std::string str; bool bExit = true; while(bExit) { void * lpCompletionKey = NULL; if (GetQueuedCompletionStatus(fdf, &BytesTransferred, (LPDWORD)&PerHandleData, (LPOVERLAPPED *) &PerIoData, INFINITE) == 0) { printf("GetQueuedCompletionStatus failed with error %d/n", GetLastError()); continue; } static int aa = 1; if(aa == 1) { aa++; str.assign(PerIoData->Buffer); } switch ( PerIoData->nOperationType ) { case OP_READ: // 完成一个接收请求 { Flags = 0; ZeroMemory(&(PerIoData->Overlapped), sizeof(OVERLAPPED)); char buffer[DATA_BUFSIZE]; memset(buffer,0,DATA_BUFSIZE); PerIoData->DataBuf.len = DATA_BUFSIZE; PerIoData->DataBuf.buf = 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; } } if(RecvBytes == 0) { bExit = false; closesocket(PerHandleData->Socket); } str.append(buffer); } break; case OP_WRITE: case OP_ACCEPT: break; } Sleep(1000); } return 0; }