最近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;
}