iocp模型客户端

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

}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值