IOCP 模型1

// IOCP.cpp : Defines the entry point for the console application.
//
//

#include "stdafx.h"

#include <WinSock2.h>
#include <Windows.h>
#include <process.h>
#pragma comment(lib, "WS2_32.lib")

#define MAX_BUFFER    256
#define MAX_TIMEOUT 1000
#define MAX_SOCKET  1024
#define MAX_THREAD    64

typedef enum _OPERATION_INFO_
{
    OP_NULL,
    OP_READ,
    OP_WRITE
}OPERATIONINFO;

typedef struct _PER_HANDLE_DATA_
{
public:
    _PER_HANDLE_DATA_()
    {
        clean();
    }
    ~_PER_HANDLE_DATA_()
    {
        clean();
    }
protected:
    void clean()
    {
        sock = INVALID_SOCKET;
        memset(&addr, 0, sizeof(addr));
        addr.sin_addr.S_un.S_addr = INADDR_ANY;
        addr.sin_port = htons(0);
        addr.sin_family = AF_INET;
    }
public:
    SOCKET sock;
    SOCKADDR_IN addr;

}PERHANDLEDATA, *PPERHANDLEDATA;

typedef struct _PER_IO_DTATA_
{
public:
    _PER_IO_DTATA_()
    {
        clean();
    }
    ~_PER_IO_DTATA_()
    {
        clean();
    }
private:
    void clean()
    {
        ZeroMemory(&ol, sizeof(ol));
        memset(buf, 0, sizeof(buf));
        wsaBuf.buf = buf;
        wsaBuf.len = MAX_BUFFER;
        opType =  OP_NULL;
    }
public:
    WSAOVERLAPPED ol;
    WSABUF wsaBuf;
    char buf[MAX_BUFFER];
    OPERATIONINFO opType;
}PERIODATA, *PPERIODATA;

HANDLE hThread[MAX_THREAD] = {0};
int g_nThread = 0;
BOOL g_bExitThread = FALSE;

unsigned __stdcall ThreadProc(LPVOID lParam);

int _tmain(int argc, _TCHAR* argv[])
{
    WSADATA wsaData;
    if(0 != WSAStartup(MAKEWORD(2, 2), &wsaData))
    {
        printf("WSAStartup failed with error code: %d/n", GetLastError());
        return EXIT_FAILURE;
    }
    if(2 != HIBYTE(wsaData.wVersion) || 2 != LOBYTE(wsaData.wVersion))
    {
        printf("Socket version not supported./n");
        WSACleanup();
        return EXIT_FAILURE;
    }

    // Create I/O Completion Port
    HANDLE hIOCP = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, NULL, 0);
    if(NULL == hIOCP)
    {
        printf("CreateIoCompletionPort failed with error code: %d/n", GetLastError());
        WSACleanup();
        return EXIT_FAILURE;
    }
    // Create worker thread
    SYSTEM_INFO si = {0};
    GetSystemInfo(&si);
    for(int i = 0; i < (int)si.dwNumberOfProcessors+2; i++)
    {
        hThread[g_nThread] = (HANDLE)_beginthreadex(NULL, 0, ThreadProc, (LPVOID)hIOCP, 0, NULL);
        if(NULL == hThread[g_nThread])
        {
            printf("_beginthreadex failed with error code: %d/n", GetLastError());
            continue;
        }
        ++g_nThread;

        if(g_nThread > MAX_THREAD)
        {
            break;
        }
    }

    // Create socket
    SOCKET sListen = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED);
    if(INVALID_SOCKET == sListen)
    {
        printf("WSASocket failed with error code: %d/n", WSAGetLastError());
        goto EXIT_CODE;
    }
    SOCKADDR_IN addr;
    memset(&addr, 0, sizeof(addr));
    addr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
    addr.sin_family = AF_INET;
    addr.sin_port = htons(5050);
    if(SOCKET_ERROR == bind(sListen, (LPSOCKADDR)&addr, sizeof(addr)))
    {
        printf("bind failed with error code: %d/n", WSAGetLastError());
        closesocket(sListen);
        sListen = INVALID_SOCKET;
        goto EXIT_CODE;
    }
    if(SOCKET_ERROR == listen(sListen, 5))
    {
        printf("listen failed with error code: %d/n", WSAGetLastError());
        closesocket(sListen);
        sListen = INVALID_SOCKET;
        goto EXIT_CODE;
    }

    printf("Server start, wait for client to connect .../n");
    while(TRUE)
    {
        SOCKADDR_IN remote;
        memset(&remote, 0, sizeof(remote));
        int len = sizeof(remote);

        SOCKET sNew = WSAAccept(sListen, (LPSOCKADDR)&remote, &len, NULL, NULL);
        if(INVALID_SOCKET == sNew)
        {
            printf("WSAAccept failed with error code: %d/n", WSAGetLastError());
            continue;
        }
        printf("Client <%s : %d> come in./n", inet_ntoa(remote.sin_addr), ntohs(remote.sin_port));
        PERHANDLEDATA* pPerHandleData = new PERHANDLEDATA;
        pPerHandleData->sock = sNew;
        memcpy(&(pPerHandleData->addr), &remote, sizeof(remote));
        // Associate with IOCP
        if(NULL == CreateIoCompletionPort((HANDLE)(pPerHandleData->sock), hIOCP, (ULONG_PTR)pPerHandleData, 0))
        {
            printf("CreateIoCompletionPort failed with error code: %d/n", GetLastError());
            closesocket(pPerHandleData->sock);
            delete pPerHandleData;
            continue;
        }
        // Post Receive
        PERIODATA* pPerIoData = new PERIODATA;
        pPerIoData->opType = OP_READ;
        DWORD dwTrans = pPerIoData->wsaBuf.len;
        DWORD dwFlags = 0;
        if(SOCKET_ERROR == WSARecv(pPerHandleData->sock, &(pPerIoData->wsaBuf), 1,
            &dwTrans, &dwFlags, &(pPerIoData->ol), NULL))
        {
            if(WSA_IO_PENDING != WSAGetLastError())
            {
                printf("WSARecv failed with error code: %d/n", WSAGetLastError());
                closesocket(pPerHandleData->sock);
                delete pPerHandleData;
                delete pPerIoData;
                continue;
            }
        }
    }
    closesocket(sListen);
    sListen = INVALID_SOCKET;

EXIT_CODE:
    g_bExitThread = TRUE;
    PostQueuedCompletionStatus(hIOCP, 0, NULL, NULL);
    WaitForMultipleObjects(g_nThread, hThread, TRUE, INFINITE);
    for(int i = 0; i < g_nThread; i++)
    {
        CloseHandle(hThread[g_nThread]);
    }
    CloseHandle(hIOCP); // Close IOCP
    WSACleanup();
    return 0;
}

unsigned __stdcall ThreadProc(LPVOID lParam)
{
    HANDLE hIOCP = (HANDLE)lParam;

    PERHANDLEDATA* pPerHandleData = NULL;
    PERIODATA* pPerIoData = NULL;
    WSAOVERLAPPED* lpOverlapped = NULL;
    DWORD dwTrans = 0;
    DWORD dwFlags = 0;
    while(!g_bExitThread)
    {
        BOOL bRet = GetQueuedCompletionStatus(hIOCP, &dwTrans, (PULONG_PTR)&pPerHandleData, &lpOverlapped, INFINITE);
        if(!bRet)
        {
            printf("GetQueuedCompletionStatus failed with error: %d/n", WSAGetLastError());
            continue;
        }
        else
        {
            pPerIoData = CONTAINING_RECORD(lpOverlapped, PERIODATA, ol);
            if(0 == dwTrans)
            {
                printf("Client: <%s : %d> leave./n", inet_ntoa(pPerHandleData->addr.sin_addr), ntohs(pPerHandleData->addr.sin_port));
                closesocket(pPerHandleData->sock);
                delete pPerHandleData;
                delete pPerIoData;
                continue;
            }
            else
            {
                switch(pPerIoData->opType)
                {
                case OP_READ:
                    printf("recv client <%s : %d> data: %s/n", inet_ntoa(pPerHandleData->addr.sin_addr), ntohs(pPerHandleData->addr.sin_port), pPerIoData->buf);
                    pPerIoData->opType = OP_WRITE;
                    memset(&(pPerIoData->ol), 0, sizeof(pPerIoData->ol));
                    if(SOCKET_ERROR == WSASend(pPerHandleData->sock, &(pPerIoData->wsaBuf), 1, &dwTrans, dwFlags, &(pPerIoData->ol), NULL))
                    {
                        if(WSA_IO_PENDING != WSAGetLastError())
                        {
                            printf("WSASend failed with error code: %d./n", WSAGetLastError());
                            continue;
                        }
                    }
                    break;

                case OP_WRITE:
                    {
                        pPerIoData->opType = OP_READ;
                        dwFlags = 0;
                        memset(&(pPerIoData->ol), 0, sizeof(pPerIoData->ol));
                        memset(pPerIoData->buf, 0, sizeof(pPerIoData->buf));
                        pPerIoData->wsaBuf.buf = pPerIoData->buf;
                        dwTrans = pPerIoData->wsaBuf.len = MAX_BUFFER;
                        if(SOCKET_ERROR == WSARecv(pPerHandleData->sock, &(pPerIoData->wsaBuf), 1, &dwTrans, &dwFlags, &(pPerIoData->ol), NULL))
                        {
                            if(WSA_IO_PENDING != WSAGetLastError())
                            {
                                printf("WSARecv failed with error code: %d./n", WSAGetLastError());
                                continue;
                            }
                        }
                    }
                    break;

                default:
                    break;
                }
            }
        }
    }
    return 0;
}
时间: 2024-11-29 22:34:22

IOCP 模型1的相关文章

IOCP模型总结(总结回顾)

IOCP旧代码重提,最近一直在玩其他方面的东东,时不时回顾一下,收益多多. IOCP(I/O Completion Port,I/O完成端口)是性能最好的一种I/O模型.它是应用程序使用线程池处理异步I/O请求的一种机制.在处理多个并发的异步I/O请求时,以往的模型都是在接收请求是创建一个线程来应答请求.这样就有很多的线程并行地运行在系统中.而这些线程都是可运行的,Windows内核花费大量的时间在进行线程的上下文切换,并没有多少时间花在线程运行上.再加上创建新线程的开销比较大,所以造成了效率的

Window下高性能IOCP模型队列多线程下应用

IOCP,先从概念上认识一下.IOCP全称I/O Completion Port,中文译为I/O完成端口.是Windows平台最高效的I/O模块,现在IIS服务器,就采用IOCP模型.IOCP是一个异步I/O的API,它可以高效地将I/O事件通知给应用程序.与使用select()或是其它异步方法不同的是,现在很多书,文字都直接将IOCP模块和网络编程关联起来,好像IOCP就是和网络打交道的.典型的IOCP模型的使用,是 将一个套接字(socket)与一个完成端口关联了起来,当一个网络事件发生的时

IOCP模型与网络编

一.前言:        在老师分配任务(“尝试利用IOCP模型写出服务端和客户端的代码”)给我时,脑子一片空白,并不知道什么是IOCP模型,会不会是像软件设计模式里面的工厂模式,装饰模式之类的那些呢?嘿嘿,不过好像是一个挺好玩的东西,挺好奇是什么东西来的,又是一个新知识啦~于是,开始去寻找一大堆的资料,为这个了解做准备,只是呢,有时还是想去找一本书去系统地学习一下,毕竟网络的资料还是有点零散.话说,本人学习这个模型的基础是,写过一个简单的Socket服务器及客户端程序,外加一个简单的Socke

IOCP模型与网络编程

IOCP模型与网络编程 一.前言:        在老师分配任务("尝试利用IOCP模型写出服务端和客户端的代码")给我时,脑子一片空白,并不知道什么是IOCP模型,会不会是像软件设计模式里面的工厂模式,装饰模式之类的那些呢?嘿嘿,不过好像是一个挺好玩的东西,挺好奇是什么东西来的,又是一个新知识啦~于是,开始去寻找一大堆的资料,为这个了解做准备,只是呢,有时还是想去找一本书去系统地学习一下,毕竟网络的资料还是有点零散.话说,本人学习这个模型的基础是,写过一个简单的Socket服务器及客

winsock编程IOCP模型实现代码

winsock编程IOCP模型实现代码 话不多说,上代码.借鉴<windows核心编程>部分源码和CSDN小猪部分代码. stdafx.h依赖头文件: 1 #include <iostream> 2 #include <WinSock2.h> 3 #include <MSWSock.h> 4 #include <vector> 5 #include "Singleton.h" 6 #include "IOCPWrap

IOCP模型

IOCP http://blog.csdn.net/zhongguoren666/article/details/7386592 Winsock IO模型之IOCP模型 http://blog.csdn.net/lostyears/article/details/7436802

对于TCP协议中IOCP模型的一些简单的理解

请不要觉得这一篇没有代码的文章没意义,对IOCP模型的代码,百度搜索可以得到很多,但是后续很多需要纠结的地方,很多人都经历过,如果你已经在尝试写IOCP服务端了,那么你很可能会对写代码之外的一些设计问题很纠结,那么本文很可能是对你有所帮助的,这一个帖子是我开的讨论帖,我不是很懂CSDN的帖子分数的意义,我觉得那对于我这种1年难得发1贴的人来说估计也没什么作用,但我很希望大家能一起参与进来讨论:http://bbs.csdn.net/topics/390890567?page=1#post-398

Nginx源码分析 - Nginx启动以及IOCP模型

Nginx 源码分析 - Nginx启动以及IOCP模型 版本及平台信息 本文档针对Nginx1.11.7版本,分析Windows下的相关代码,虽然服务器可能用linux更多,但是windows平台下的代码也基本相似 ,另外windows的IOCP完成端口,异步IO模型非常优秀,很值得一看. Nginx启动 曾经有朋友问我,面对一个大项目的源代码,应该从何读起呢?我给他举了一个例子,我们学校大一大二是在紫金港校区,到了 大三搬到玉泉校区,但是大一的时候也会有时候有事情要去玉泉办.偶尔会去玉泉,但

【IOCP】 IOCP模型属于一种通讯模型- 较难

http://baike.baidu.com/link?url=e9vXkKd2aHp8VDr1XTURdwQB4K85r28IYjeMwRIyuaXtsrCsXHY1eohiFgsDXRYRlj6xEQoZFzH9dgKwla2n3q IOCP(I/O Completion Port),常称I/O完成端口. IOCP模型属于一种通讯模型,适用于(能控制并发执行的)高负载服务器的一个技术. 通俗一点说,就是用于高效处理很多很多的客户端进行数据交换的一个模型.或者可以说,就是能异步I/O操作的模型

IOCP模型、EPOLL模型的比较以及游戏服务器端的一些建议

一:IOCP和Epoll之间的异同.异:1:IOCP是WINDOWS系统下使用.Epoll是Linux系统下使用.2:IOCP是IO操作完毕之后,通过Get函数获得一个完成的事件通知.Epoll是当你希望进行一个IO操作时,向Epoll查询是否可读或者可写,若处于可读或可写状态后,Epoll会通过epoll_wait进行通知.3:IOCP封装了异步的消息事件的通知机制,同时封装了部分IO操作.但Epoll仅仅封装了一个异步事件的通知机制,并不负责IO读写操作.Epoll保持了事件通知和IO操作间