IOCP完整例子

转载 2015年07月08日 15:27:22
/************************************************************************

		FileName:iocp.h
		Author	:eliteYang

http://www.cppfans.org

************************************************************************/
#ifndef __IOCP_H__
#define __IOCP_H__

#include
#include 

#define DefaultPort 20000
#define DataBuffSize 8 * 1024

typedef struct
{
	OVERLAPPED overlapped;
	WSABUF databuff;
	CHAR buffer[ DataBuffSize ];
	DWORD bytesSend;
	DWORD bytesRecv;
}PER_IO_OPERATEION_DATA, *LPPER_IO_OPERATION_DATA;

typedef struct
{
	SOCKET socket;
}PER_HANDLE_DATA, *LPPER_HANDLE_DATA;

#endif
前面讲过IOCP里面一个很重要的东西就是IO重叠了,所以结构体里有一个OVERLAPPED结构。
/************************************************************************

		FileName:iocp.cpp
		Author	:eliteYang

http://www.cppfans.org

************************************************************************/

#include "iocp.h"
#include 

using namespace std;

#pragma comment( lib, "Ws2_32.lib" )

DWORD WINAPI ServerWorkThread( LPVOID CompletionPortID );

void main()
{

	SOCKET acceptSocket;
	HANDLE completionPort;
	LPPER_HANDLE_DATA pHandleData;
	LPPER_IO_OPERATION_DATA pIoData;
	DWORD recvBytes;
	DWORD flags;

	WSADATA wsaData;
	DWORD ret;
	if ( ret = WSAStartup( 0x0202, &wsaData ) != 0 )
	{
		std::cout << "WSAStartup failed. Error:" << ret << std::endl;
		return;
	}

	completionPort = CreateIoCompletionPort( INVALID_HANDLE_VALUE, NULL, 0, 0 );
	if ( completionPort == NULL )
	{
		std::cout << "CreateIoCompletionPort failed. Error:" << GetLastError() << std::endl;
		return;
	}

	SYSTEM_INFO mySysInfo;
	GetSystemInfo( &mySysInfo );

	// 创建 2 * CPU核数 + 1 个线程
	DWORD threadID;
	for ( DWORD i = 0; i < ( mySysInfo.dwNumberOfProcessors * 2 + 1 ); ++i )
	{
		HANDLE threadHandle;
		threadHandle = CreateThread( NULL, 0, ServerWorkThread, completionPort, 0, &threadID );
		if ( threadHandle == NULL )
		{
			std::cout << "CreateThread failed. Error:" << GetLastError() << std::endl;
			return;
		}

		CloseHandle( threadHandle );
	}

	// 启动一个监听socket
	SOCKET listenSocket = WSASocket( AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED );
	if ( listenSocket == INVALID_SOCKET )
	{
		std::cout << " WSASocket( listenSocket ) failed. Error:" << GetLastError() << std::endl;
		return;
	}

	SOCKADDR_IN internetAddr;
	internetAddr.sin_family = AF_INET;
	internetAddr.sin_addr.s_addr = htonl( INADDR_ANY );
	internetAddr.sin_port = htons( DefaultPort );

	// 绑定监听端口
	if ( bind( listenSocket, (PSOCKADDR)&internetAddr, sizeof( internetAddr ) ) == SOCKET_ERROR )
	{
		std::cout << "Bind failed. Error:" << GetLastError() << std::endl;
		return;
	}

	if ( listen( listenSocket, 5 ) ==  SOCKET_ERROR )
	{
		std::cout << "listen failed. Error:" << GetLastError() << std::endl;
		return;
	}

	// 开始死循环,处理数据
	while ( 1 )
	{
		acceptSocket = WSAAccept( listenSocket, NULL, NULL, NULL, 0 );
		if ( acceptSocket == SOCKET_ERROR )
		{
			std::cout << "WSAAccept failed. Error:" << GetLastError() << std::endl;
			return;
		}

		pHandleData = (LPPER_HANDLE_DATA)GlobalAlloc( GPTR, sizeof( PER_HANDLE_DATA ) );
		if ( pHandleData = NULL )
		{
			std::cout << "GlobalAlloc( HandleData ) failed. Error:" << GetLastError() << std::endl;
			return;
		}

		pHandleData->socket = acceptSocket;
		if ( CreateIoCompletionPort( (HANDLE)acceptSocket, completionPort, (ULONG_PTR)pHandleData, 0 ) == NULL )
		{
			std::cout << "CreateIoCompletionPort failed. Error:" << GetLastError() << std::endl;
			return;
		}

		pIoData = ( LPPER_IO_OPERATION_DATA )GlobalAlloc( GPTR, sizeof( PER_IO_OPERATEION_DATA ) );
		if ( pIoData == NULL )
		{
			std::cout << "GlobalAlloc( IoData ) failed. Error:" << GetLastError() << std::endl;
			return;
		}

		ZeroMemory( &( pIoData->overlapped ), sizeof( pIoData->overlapped ) );
		pIoData->bytesSend = 0;
		pIoData->bytesRecv = 0;
		pIoData->databuff.len = DataBuffSize;
		pIoData->databuff.buf = pIoData->buffer;

		flags = 0;
		if ( WSARecv( acceptSocket, &(pIoData->databuff), 1, &recvBytes, &flags, &(pIoData->overlapped), NULL ) == SOCKET_ERROR )
		{
			if ( WSAGetLastError() != ERROR_IO_PENDING )
			{
				std::cout << "WSARecv() failed. Error:" << GetLastError() << std::endl;
				return;
			}
			else
			{
				std::cout << "WSARecv() io pending" << std::endl;
				return;
			}
		}
	}
}

DWORD WINAPI ServerWorkThread( LPVOID CompletionPortID )
{
	HANDLE complationPort = (HANDLE)CompletionPortID;
	DWORD bytesTransferred;
	LPPER_HANDLE_DATA pHandleData = NULL;
	LPPER_IO_OPERATION_DATA pIoData = NULL;
	DWORD sendBytes = 0;
	DWORD recvBytes = 0;
	DWORD flags;

	while ( 1 )
	{
		if ( GetQueuedCompletionStatus( complationPort, &bytesTransferred, (PULONG_PTR)&pHandleData, (LPOVERLAPPED *)&pIoData, INFINITE ) == 0 )
		{
			std::cout << "GetQueuedCompletionStatus failed. Error:" << GetLastError() << std::endl;
			return 0;
		}

		// 检查数据是否已经传输完了
		if ( bytesTransferred == 0 )
		{
			std::cout << " Start closing socket..." << std::endl;
			if ( CloseHandle( (HANDLE)pHandleData->socket ) == SOCKET_ERROR )
			{
				std::cout << "Close socket failed. Error:" << GetLastError() << std::endl;
				return 0;
			}

			GlobalFree( pHandleData );
			GlobalFree( pIoData );
			continue;
		}

		// 检查管道里是否有数据
		if ( pIoData->bytesRecv == 0 )
		{
			pIoData->bytesRecv = bytesTransferred;
			pIoData->bytesSend = 0;
		}
		else
		{
			pIoData->bytesSend += bytesTransferred;
		}

		// 数据没有发完,继续发送
		if ( pIoData->bytesRecv > pIoData->bytesSend )
		{
			ZeroMemory( &(pIoData->overlapped), sizeof( OVERLAPPED ) );
			pIoData->databuff.buf = pIoData->buffer + pIoData->bytesSend;
			pIoData->databuff.len = pIoData->bytesRecv - pIoData->bytesSend;

			// 发送数据出去
			if ( WSASend( pHandleData->socket, &(pIoData->databuff), 1, &sendBytes, 0, &(pIoData->overlapped), NULL ) == SOCKET_ERROR )
			{
				if ( WSAGetLastError() != ERROR_IO_PENDING )
				{
					std::cout << "WSASend() failed. Error:" << GetLastError() << std::endl;
					return 0;
				}
				else
				{
					std::cout << "WSASend() failed. io pending. Error:" << GetLastError() << std::endl;
					return 0;
				}
			}

			std::cout << "Send " << pIoData->buffer << std::endl;
		}
		else
		{
			pIoData->bytesRecv = 0;
			flags = 0;

			ZeroMemory( &(pIoData->overlapped), sizeof( OVERLAPPED ) );
			pIoData->databuff.len = DataBuffSize;
			pIoData->databuff.buf = pIoData->buffer;

			if ( WSARecv( pHandleData->socket, &(pIoData->databuff), 1, &recvBytes, &flags, &(pIoData->overlapped), NULL ) == SOCKET_ERROR )
			{
				if ( WSAGetLastError() != ERROR_IO_PENDING )
				{
					std::cout << "WSARecv() failed. Error:" << GetLastError() << std::endl;
					return 0;
				}
				else
				{
					std::cout << "WSARecv() io pending" << std::endl;
					return 0;
				}
			}
		}
	}
}

IOCP完整例子

本文是我在学习IOCP的时候,第一次写一个完整的例子出来,当然了,参考了CSDN上一些朋友的博客,大部分都是按照他们的思路写的,毕竟我是初学者,参考现成的学起来比较快。当然了,真正用到项目中的IOCP...
  • zhujunxxxxx
  • zhujunxxxxx
  • 2014年02月28日 09:58
  • 2300

简单的IOCP例子

使用IOCP模型编程的优点  ① 帮助维持重复使用的内存池。(与重叠I/O技术有关)  ② 去除删除线程创建/终结负担。  ③ 利于管理,分配线程,控制并发,最小化的线程上下文切换。  ④ 优...
  • hkwlg1314
  • hkwlg1314
  • 2015年10月29日 17:01
  • 188

windows下简单的IOCP模型迭代回声服务器实例

#include #include #include #include #pragma comment(lib,"ws2_32.lib") #define BUF_SIZE 100 #define R...
  • zl908760230
  • zl908760230
  • 2017年04月25日 16:04
  • 476

libevent使用IOCP网络模型的示例

这段时间抽空研究了一下强大的网络库libevent,其使用标准C语言编写,支持Windows、Linux、Mac等等主流操作系统,早期版本不支持Windows的IOCP,最新版本已经添加上了,在网上找...
  • witton
  • witton
  • 2016年07月01日 15:09
  • 3632

完成端口(IOCP)实现高性能网络服务器(源码 C#)

完成端口(IOCP)实现高性能网络服务器(源码 C#) 最近有项目要做一个高性能网络服务器,决定下功夫搞定完成端口(IOCP),最终花了一个星期终于把它弄清楚了,并用C++写了一个版本,效率很不...
  • luxiaoyu_sdc
  • luxiaoyu_sdc
  • 2013年11月21日 15:31
  • 1593

IOCP 浅析与实例

这一年半来一直在做游戏项目逻辑层,学会了不少东西,觉得自己应该看看服务器底层的东西了,主要的东西就是网络模块,网络模块是沿用以前项目的,在 我们项目中被我们头改动过几次,现在还是比较稳定的。因为是Wi...
  • liujiayu2
  • liujiayu2
  • 2015年06月10日 19:15
  • 597

用完成端口(iocp) 写的一个简单的服务端例子

下面是用完成端口写的一个简单的 例子, 完成端口和重叠io 一样都是异步io。 代码如下。欢迎大家建议 改进、...
  • billiejeannotmylover
  • billiejeannotmylover
  • 2014年01月11日 00:54
  • 1424

简单IOCP例子

简单IOCP例子
  • ggz631047367
  • ggz631047367
  • 2015年04月11日 16:06
  • 4277

delphi之IOCP学习(一)

delphi之IOCP学习(一)    困扰已久的网络通信(IOCP:完成端口),今天终于揭开她的神秘面纱了,之前百度N久还是未能理解IOCP,网络上好多博文都没有贴出源码,初学者很难正在理...
  • u013051638
  • u013051638
  • 2016年11月25日 16:37
  • 334

IOCP 基本模型 事例

送上事例前先回忆一下IOCP的步骤 1、创建一个完完成端口 2、创建一个线程A 3、A线程循环调用GetQueuedCompletionStatus()函数来得到IO操作结果,这个函数是阻塞函数 4、...
  • machuanfei_c
  • machuanfei_c
  • 2016年01月09日 21:29
  • 910
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:IOCP完整例子
举报原因:
原因补充:

(最多只允许输入30个字)