IO Completion Port简明教程(含例程)(7)

2025-10-04

WSADATA wsaData;

if( 0 != WSAStartup( MAKEWORD( 2, 2 ), &wsaData ) ) {

printf( \wsaData.szSystemStatus );

printf( \ LOBYTE( wsaData.wVersion), HIBYTE( wsaData.wVersion ),

LOBYTE( wsaData.wHighVersion), HIBYTE( wsaData.wHighVersion) );

return -1; } else {

printf(\ }

//////////////////////////////////////////////////////////////////////////

int nPort = 20055;

// 创建完成端口对象

// 创建工作线程处理完成端口对象的事件

HANDLE hIocp = ::CreateIoCompletionPort( INVALID_HANDLE_VALUE, 0, 0, 0 );

::CreateThread( NULL, 0, ServerThread, (LPVOID)hIocp, 0, 0 ); // 创建监听套接字,绑定本地端口,开始监听

SOCKET sListen = ::socket( AF_INET,-SOCK_STREAM, 0 ); SOCKADDR_IN addr;

addr.sin_family = AF_INET;

addr.sin_port = ::htons( nPort );

addr.sin_addr.S_un.S_addr = INADDR_ANY;

::bind( sListen, (sockaddr *)&addr, sizeof( addr ) ); ::listen( sListen, 5 );

printf( \ // 循环处理到来的请求 while ( TRUE ) {

// 等待接受未决的连接请求

SOCKADDR_IN saRemote;

int nRemoteLen = sizeof( saRemote );

SOCKET sRemote = ::accept( sListen, (sockaddr *)&saRemote, &nRemoteLen );

// 接受到新连接之后,为它创建一个per_handle数据,并将他们关联到完成端口对象

PPER_HANDLE_DATA pPerHandle =

( PPER_HANDLE_DATA )::GlobalAlloc( GPTR, sizeof( PPER_HANDLE_DATA ) ); if( pPerHandle == NULL ) {

break; }

pPerHandle->s = sRemote;

memcpy( &pPerHandle->addr, &saRemote, nRemoteLen ); ::CreateIoCompletionPort( ( HANDLE)pPerHandle->s, hIocp, (DWORD)pPerHandle, 0 );

// 投递一个接受请求

PPER_IO_DATA pIoData = ( PPER_IO_DATA )::GlobalAlloc( GPTR, sizeof( PPER_IO_DATA ) );

if( pIoData == NULL ) {

break; }

pIoData->nOperationType = OP_READ; WSABUF buf;

buf.buf = pIoData->buf; buf.len = BUFFER_SIZE;

DWORD dwRecv = 0; DWORD dwFlags = 0;

::WSARecv( pPerHandle->s, &buf, 1, &dwRecv, &dwFlags, &pIoData->ol, NULL ); }

////////////////////////////////////////////////////////////////////////// ERROR_PROC:

WSACleanup();

////////////////////////////////////////////////////////////////////////// return 0; }

/****************************************************************** * 函数介绍:处理完成端口对象事件的线程 * 输入参数: * 输出参数: * 返回值 :

*******************************************************************/ DWORD WINAPI ServerThread( LPVOID lpParam ) {

HANDLE hIocp = ( HANDLE )lpParam; if( hIocp == NULL ) {

return -1; }

DWORD dwTrans = 0;

PPER_HANDLE_DATA pPerHandle; PPER_IO_DATA pPerIo;

while( TRUE ) {

// 在关联到此完成端口的所有套接字上等待I/O完成

BOOL bRet = ::GetQueuedCompletionStatus( hIocp, &dwTrans, (LPDWORD)&pPerHandle, (LPOVERLAPPED*)&pPerIo, WSA_INFINITE ); if( !bRet ) // 发生错误 {

::closesocket( pPerHandle->s ); ::GlobalFree( pPerHandle ); ::GlobalFree( pPerIo ); cout << \ continue; }

// 套接字被对方关闭

if( dwTrans == 0 && ( pPerIo->nOperationType == OP_READ || pPerIo->nOperationType&nb-sp;== OP_WRITE ) ) {

::closesocket( pPerHandle->s );

::GlobalFree( pPerHandle ); ::GlobalFree( pPerIo );

cout << \ continue; }

switch ( pPerIo->nOperationType ) {

case OP_READ: // 完成一个接收请求 {

pPerIo->buf[dwTrans] = '\\0'; printf( \

// 继续投递接受操作 WSABUF buf;

buf.buf = pPerIo->buf; buf.len = BUFFER_SIZE;

pPerIo->nOperationType = OP_READ;

DWORD dwRecv = 0; DWORD dwFlags = 0;

::WSARecv( pPerHandle->s, &buf, 1, &dwRecv, &dwFlags, &pPerIo->ol, NULL ); }

break;

case OP_WRITE: case OP_ACCEPT: break; } }

return 0; }

(完)

欢迎阅读此篇IOCP教程。我将先给出IOCP的定义然后给出它的实现方法,最后剖析一个Echo程序来为您拨开IOCP的谜云,除去你心中对IOCP的烦恼。OK,但我不能保证你明白IOCP的一切,但我会尽我最大的努力。以下是我会在这篇文章中提到的相关技术: ? ? ? ? ? ?

I/O端口 同步/异步 堵塞/非堵塞 服务端/客户端 多线程程序设计 Winsock API 2.0

在这之前,我曾经开发过一个项目,其中一块需要网络支持,当时还考虑到了代码的可移植性,只要使用 select,connect,accept,listen,send还有recv,再加上几个#ifdef的封装以用来处理Winsock和BSD套接字[socket]中间的不兼容性,一个网络子系统只用了几个小时很少的代码就写出来了,至今还让我很回味。那以后很长时间也就没再碰了。

前些日子,我们策划做一个网络游戏,我主动承担下网络这一块,想想这还不是小case,心里偷着乐啊。网络游戏好啊,网络游戏为成百上千的玩家提供了乐趣和令人着秘的游戏体验,他们在线上互相战斗或是加入队伍去战胜共同的敌人。我信心满满的准备开写我的网络,于是乎,发现过去的阻塞同步模式模式根本不能拿到一个巨量多玩家[MMP]的架构中去,直接被否定掉了。于是乎,就有了IOCP,如果能过很轻易而举的搞掂IOCP,也就不会有这篇教程了。下面请诸位跟随我进入正题。

什么是IOCP?

先让我们看看对IOCP的评价

I/O完成端口可能是Win32提供的最复杂的内核对象。 [Advanced Windows 3rd] Jeffrey Richter 这是[IOCP]实现高容量网络服务器的最佳方法。

[Windows Sockets2.0:Write Scalable Winsock Apps Using Completion Ports] Microsoft Corporation

完成端口模型提供了最好的伸缩性。这个模型非常适用来处理数百乃至上千个套接字。 [Windows网络编程2nd] Anthony Jones & Jim Ohlund

I/O completion ports特别显得重要,因为它们是唯一适用于高负载服务器[必须同时维护许多连接线路]的一个技术。Completion ports利用一些线程,帮助平衡由I/O请求所引起的负载。这样的架构特别适合用在SMP系统中产生的”scalable”服务器。 [Win32多线程程序设计] Jim Beveridge & Robert Wiener

看来我们完全有理由相信IOCP是大型网络架构的首选。那IOCP到底是什么呢?

微软在Winsock2中引入了IOCP这一概念 。IOCP全称I/O Completion Port,中文译为I/O完成端口。IOCP是一个异步I/O的API,它可以高效地将I/O事件通知给应用程序。与使用select()或是其它异步方法不同的是,一个套接字[socket]与一个完成端口关联了起来,然后就可继续进行正常的Winsock操作了。然而,当一个事件发生的时候,此完成端口就将被操


IO Completion Port简明教程(含例程)(7).doc 将本文的Word文档下载到电脑 下载失败或者文档不完整,请联系客服人员解决!

下一篇:Unit10 Places of Interest_ppt

相关阅读
本类排行
× 游客快捷下载通道(下载后可以自由复制和排版)

下载本文档需要支付 7

支付方式:

开通VIP包月会员 特价:29元/月

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信:xuecool-com QQ:370150219