三棵树

导航

IOCP

/****************************************************************** 
* 
* Copyright (c) 2008, xxxxx有限公司 
* All rights reserved. 
* 
* 文件名称:IOCPHeader.h 
* 摘   要: IOCP定义文件 
* 
* 当前版本:1.0 
* 作    者:吴会然 
* 完成日期:2008-9-16 
* 
* 取代版本: 
* 原 作者: 
* 完成日期: 
* 
******************************************************************/
#ifndef _IOCPHEADER_H_20080916_ 
#define _IOCPHEADER_H_20080916_
#include <WINSOCK2.H> 
#include <windows.h>
#define BUFFER_SIZE 1024
/****************************************************************** 
* per_handle 数据 
*******************************************************************/ 
typedef struct _PER_HANDLE_DATA 
{ 
    SOCKET      s;      // 对应的套接字句柄 
    sockaddr_in addr;   // 对方的地址
}PER_HANDLE_DATA, *PPER_HANDLE_DATA;
/****************************************************************** 
* per_io 数据 
*******************************************************************/ 
typedef struct _PER_IO_DATA 
{ 
    OVERLAPPED ol;                 // 重叠结构 
    char        buf[BUFFER_SIZE];   // 数据缓冲区 
    int         nOperationType;     // 操作类型
#define OP_READ   1 
#define OP_WRITE 2 
#define OP_ACCEPT 3
}PER_IO_DATA, *PPER_IO_DATA;
#endif
/****************************************************************** 
* 
* Copyright (c) 2008, xxxxx有限公司 
* All rights reserved. 
* 
* 文件名称:main.cpp 
* 摘   要: iocp demo 
* 
* 当前版本:1.0 
* 作    者:吴会然 
* 完成日期:2008-9-16 
* 
* 取代版本: 
* 原 作者: 
* 完成日期: 
* 
******************************************************************/
#include <iostream> 
#include <string> 
#include "IOCPHeader.h" 
using namespace std;
DWORD WINAPI ServerThread( LPVOID lpParam );
int main( int argc, char *argv[] ) 
{ 
    //////////////////////////////////////////////////////////////////////////   
    WSADATA wsaData;
    if( 0 != WSAStartup( MAKEWORD( 2, 2 ), &wsaData ) ) 
    { 
        printf( "Using %s (Status:%s)/n", wsaData.szDescription, wsaData.szSystemStatus ); 
        printf( "with API versions: %d.%d to %d.%d", 
                 LOBYTE( wsaData.wVersion), HIBYTE( wsaData.wVersion ), 
                 LOBYTE( wsaData.wHighVersion), HIBYTE( wsaData.wHighVersion) );
        return -1; 
    } 
    else 
    { 
        printf("Windows sockets 2.2 startup/n"); 
    } 
    //////////////////////////////////////////////////////////////////////////
    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( "iocp demo start....../n" );
    // 循环处理到来的请求 
    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 << "error" << endl; 
            continue; 
        }
        // 套接字被对方关闭 
        if( dwTrans == 0 && ( pPerIo->nOperationType == OP_READ || pPerIo->nOperationType&nb-sp;== OP_WRITE ) ) 
        { 
            ::closesocket( pPerHandle->s ); 
            ::GlobalFree( pPerHandle ); 
            ::GlobalFree( pPerIo );
            cout << "client closed" << endl; 
            continue; 
        }
        switch ( pPerIo->nOperationType ) 
        { 
        case OP_READ:       // 完成一个接收请求 
            { 
                pPerIo->buf[dwTrans] = '/0'; 
                printf( "%s/n", pPerIo->buf );
                // 继续投递接受操作 
                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; 
}
View Code

 

posted on 2017-11-27 08:38  三棵树  阅读(181)  评论(0编辑  收藏  举报