摘自网上:

IOCP配合AcceptEx的例子(1)(发表时间: 2006-7-2 14:33:00)

【评论】 【打印】 【字体:大 中 小】 本文链接:http://blog.pfan.cn/marks/16316.html 复制链接

分享到:0

标签:C++ VC 网络 服务器

在论坛找到的,搬进来备查,呵呵

感谢作者的辛苦劳动:)

作者:chang290      发表时间:2005-12-17 16:38:00   


这是在学《Windows网络编程(第二版)》第六章时制作的一个例子
由于书中没有给出简洁的例子,本人在学这里时就费了很多时间。
现在把完成的代码贴出来,供大家参考。
下面包括了主程序部分,工作线程在(2)中贴出,由于代码太长。
本程序在VS2003编译器编译运行。在6.0下可能需要稍加修改。

#include <iostream>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <mswsock.h>    //微软扩展的类库

using namespace std;
#define SEND 0
#define RECV 1
#define ACCEPT 2

#define DATA_LENGTH 1000
//单句柄数据定义
typedef struct _PER_HANDLE_DATA
{
    SOCKET socket;    //相关的套接字
    SOCKADDR_STORAGE clientAddr;    //客户端的地址
}PER_HANDLE_DATA,*LPPER_HANDLE_DATA;

//但IO操作数据
typedef struct{
    OVERLAPPED overlapped;
    WSABUF buffer;    //一个数据缓冲区,用于WSASend/WSARecv中的第二个参数
    char dataBuffer[DATA_LENGTH];    //实际的数据缓冲区
    int dataLength;                    //实际的数据缓冲区长度
    int operatorType;                //操作类型,可以为SEND/RECV两种
    SOCKET client;                    //分别表示发送的字节数和接收的字节数
}PER_IO_DATA,*LPPER_IO_DATA;

void main()
{
    HANDLE CompletionPort;
    WSADATA data;
    SYSTEM_INFO info;
    SOCKADDR_IN addr;
    SOCKET Listen;

unsigned int i;
    WSAStartup(MAKEWORD(2,2),&data);

//创建一个IO完成端口
    CompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE,NULL,0,0);
    //确定处理器的数量
    GetSystemInfo(&info);    //创建线城
    for(i=0;i<info.dwNumberOfProcessors * 2;i++)
    {
        //根据处理器的数量创建相应多的处理线程
        HANDLE thread = CreateThread(NULL,0,ServerThread,CompletionPort,0,NULL);
        CloseHandle(thread);
    }
    //创建一个监听套接字(进行重叠操作)
    Listen = WSASocket(AF_INET,SOCK_STREAM,0,NULL,0,WSA_FLAG_OVERLAPPED);
    //将监听套接字与完成端口绑定
    LPPER_HANDLE_DATA perDandleData;
    perDandleData = (LPPER_HANDLE_DATA)GlobalAlloc(GPTR,sizeof(PER_HANDLE_DATA));
    perDandleData->socket = Listen;
    CreateIoCompletionPort((HANDLE)Listen,CompletionPort,(ULONG_PTR)perDandleData,0);

addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = htonl(INADDR_ANY);
    addr.sin_port = htons(5500);

bind(Listen,(PSOCKADDR)&addr,sizeof(addr));
    listen(Listen,5);

LPFN_ACCEPTEX lpfnAcceptEx = NULL;    //AcceptEx函数指针
    //Accept function GUID
    GUID guidAcceptEx = WSAID_ACCEPTEX;
    //get acceptex function pointer
    DWORD dwBytes = 0;
    if(WSAIoctl(Listen,SIO_GET_EXTENSION_FUNCTION_POINTER,
        &guidAcceptEx,sizeof(guidAcceptEx),&lpfnAcceptEx,sizeof(lpfnAcceptEx),
        &dwBytes,NULL,NULL)==0)
        cout<<"WSAIoctl success..."<<endl;
    else{
        cout<<"WSAIoctl failed..."<<endl;
        switch(WSAGetLastError())
        {
        case WSAENETDOWN:
            cout<<""<<endl;
            break;
        case WSAEFAULT:
            cout<<"WSAEFAULT"<<endl;
            break;
        case WSAEINVAL:
            cout<<"WSAEINVAL"<<endl;
            break;
        case WSAEINPROGRESS:
            cout<<"WSAEINPROGRESS"<<endl;
            break;
        case WSAENOTSOCK:
            cout<<"WSAENOTSOCK"<<endl;
            break;
        case WSAEOPNOTSUPP:
            cout<<"WSAEOPNOTSUPP"<<endl;
            break;
        case WSA_IO_PENDING:
            cout<<"WSA_IO_PENDING"<<endl;
            break;
        case WSAEWOULDBLOCK:
            cout<<"WSAEWOULDBLOCK"<<endl;
            break;
        case WSAENOPROTOOPT:
            cout<<"WSAENOPROTOOPT"<<endl;
            break;
        }
        return;
    }

//while(true)
    //{
        //准备调用 AcceptEx 函数,该函数使用重叠结构并于完成端口连接
        LPPER_IO_DATA perIoData = (LPPER_IO_DATA)GlobalAlloc(GPTR,sizeof(PER_IO_DATA));
        memset(&(perIoData->overlapped),0,sizeof(OVERLAPPED));    
        perIoData->operatorType = ACCEPT;
        //在使用AcceptEx前需要事先重建一个套接字用于其第二个参数。这样目的是节省时间
        //通常可以创建一个套接字库
        perIoData->client = WSASocket(AF_INET,SOCK_STREAM,IPPROTO_TCP,0,0,WSA_FLAG_OVERLAPPED);

perIoData->dataLength = DATA_LENGTH;
        DWORD flags = 0;
        
        //调用AcceptEx函数,地址长度需要在原有的上面加上16个字节
        //注意这里使用了重叠模型,该函数的完成将在与完成端口关联的工作线程中处理
        cout<<"Process AcceptEx function wait for client connect..."<<endl;
        int rc = lpfnAcceptEx(Listen,perIoData->client,perIoData->dataBuffer,
            perIoData->dataLength-((sizeof(SOCKADDR_IN)+16)*2),
            sizeof(SOCKADDR_IN)+16,sizeof(SOCKADDR_IN)+16,&dwBytes,
            &(perIoData->overlapped));
        if(rc == FALSE)
        {
            if(WSAGetLastError()!=ERROR_IO_PENDING)
                cout<<"lpfnAcceptEx failed.."<<endl;
        }

cin>>i;
    closesocket(Listen);
    WSACleanup();
}

阅读(8897) | 评论(2) | 复制链接

IOCP配合AcceptEx的例子(2)(发表时间: 2006-7-2 14:36:00)

【评论】 【打印】 【字体:大 中 小】 本文链接:http://blog.pfan.cn/marks/16317.html 复制链接

分享到:0

标签:C++ VC 网络 服务器

这是在学《Windows网络编程(第二版)》第六章时制作的一个例子
由于书中没有给出简洁的例子,本人在学这里时就费了很多时间。
现在把完成的代码贴出来,供大家参考。
本程序在VS2003编译器编译运行。在6.0下可能需要稍加修改。

DWORD WINAPI ServerThread(LPVOID lpParam)
{
    HANDLE CompletionPort = (HANDLE)lpParam;
    DWORD bytes;
    LPPER_HANDLE_DATA perHandleData = NULL;    //单句柄数据
    LPPER_IO_DATA perIoData;            //单IO数据
    DWORD Flags;
    int ret;
    DWORD RecvBytes;
    //进入循环的等待重叠操作的完成
    while(true)
    {
        bytes = -1;
        ret=GetQueuedCompletionStatus(
            CompletionPort,                //原先的完成端口句柄
            &bytes,                        //重叠操作完成的字节数
            (LPDWORD)&perHandleData,    //原先和完成端口句柄关联起来的单句柄数据
            (LPOVERLAPPED*)&perIoData,    //用于接收已完成的IO操作的重叠结构
            INFINITE);                    //在完成端口上等待的时间 INFINITE 为无限等待
        
        //先检查在套接字上是否发生错误
        //当发生错误时关闭套接字同时释放掉所有的内存.
        int i = 0;
        if(bytes == 0 && (perIoData->operatorType == RECV ||
            perIoData->operatorType == SEND))
        {
            closesocket(perHandleData->socket);
            GlobalFree(perHandleData);
            GlobalFree(perIoData);
            cout<<"closesocket and globalfree perhandledata periodata!"<<endl;
            continue;
        }
        //这是AcceptEx函数处理完成,在下面处理
        if(perIoData->operatorType == ACCEPT)    //处理连接操作
        {
            //使用GetAcceptExSockaddrs函数 获得具体的各个地址参数.
            if(setsockopt( perIoData->client, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT,  
                ( char* )&(perHandleData->socket ), sizeof( perHandleData->socket ) )==SOCKET_ERROR)
                cout<<"setsockopt..."<<endl;

perHandleData->socket = perIoData->client;

//memcpy(&(perHandleData->clientAddr),raddr,sizeof(raddr));
            //将新的客户套接字与完成端口连接
            CreateIoCompletionPort((HANDLE)perHandleData->socket,
                CompletionPort,(ULONG_PTR)perHandleData,0);

memset(&(perIoData->overlapped),0,sizeof(OVERLAPPED));
            perIoData->operatorType = RECV;        //将状态设置成接收
            //设置WSABUF结构
            perIoData->buffer.buf = perIoData->dataBuffer;
            perIoData->buffer.len = perIoData->dataLength = DATA_LENGTH;

cout<<"wait for data arrive(Accept)..."<<endl;
            Flags = 0;
            if(WSARecv(perHandleData->socket,&(perIoData->buffer),1,
                &RecvBytes,&Flags,&(perIoData->overlapped),NULL)==SOCKET_ERROR)
                if(WSAGetLastError()==WSA_IO_PENDING)
                    cout<<"WSARecv Pending..."<<endl;
            continue;            
        }
        if(perIoData->operatorType == RECV)
            cout<<perIoData->buffer.buf<<endl;    //将接收到的数据显示出来
        Flags = 0;
        perIoData->operatorType = RECV;            //设置成接受数据类型

ZeroMemory(&(perIoData->overlapped),sizeof(OVERLAPPED));
        //重新投递一个新的接收请求
        cout<<" wait for data arrive..."<<endl;
        WSARecv(perHandleData->socket,&(perIoData->buffer),1,
            &RecvBytes,&Flags,&(perIoData->overlapped),NULL);
    }

return 0;
}
在前面有贴出了一个简单的客户端例子,可以结合起来调试,很方便的。
欢迎同道同志来信讨论 chang841018@yahoo.com.cn

阅读(8029) | 评论(2) | 复制链接

iocp配合acceptex相关推荐

  1. 【转】IOCP配合AcceptEx的例子

    [转]IOCP配合AcceptEx的例子 原文地址:http://laokaddk.blog.51cto.com/368606/610145/ 本程序在VS2003编译器编译运行.在6.0下可能需要稍 ...

  2. IOCP配合AcceptEx的例子

    本程序在VS2003编译器编译运行.在6.0下可能需要稍加修改. #include <iostream> #include <winsock2.h> #include < ...

  3. IOCP结合AcceptEx实例

    在普通IOCP的基础上注意两点: 1.记得把监听socket绑定到端口 2.在Accept处理过程中,抛出接受连接的AcceptEx请求,绑定客户端socket到端口和抛出recv请求 客户端要断开连 ...

  4. IOCP之AcceptEx的问题(1)

    最近在使用编写IOCP模型时,Server端使用的是AcceptEx异步 而Client端是用的Socket函数,但是在测试中遇到这种情况: CLient并发连接到Server,每次都是连接数1635 ...

  5. IOCP使用acceptEX进行异步接收

    示例代码为什么要调用WSAIoctl ()函数 #include <winsock2.h> #include <windows.h> #include <string&g ...

  6. IOCP使用acceptEx产生997错误

    997错误在解释中是重叠IO正在使用中,要么使用acceptEx没有开线程,一些结果没办法处理,要么就是在x64位系统编译中出现的问题.第二种可能 性最大.还在解决了,解决了再来更新 CSDN上对99 ...

  7. uicolor swift_Swift中的UIColor

    uicolor swift UIColor (UIColor) An object that stores color data and sometimes opacity. 存储颜色数据和有时不透明 ...

  8. IOCP扩展方法AcceptEx, DisconnectEx, GetAcceptExSockaddr用法示例

    这篇文章记录了我刚接触IOCP模型时的理解,对于初学者,应该算不错的调试程序,仅有一个400多行代码的dpr文件,可以直接用WriteLn输出信息,前提是会用delphi建立Console Appli ...

  9. 完成端口与AcceptEx

    关于IOCP网上到处都是资料,说的也很详细.我在这里就不再多说了,这只是本人在学习IOCP时的笔记,和配合AcceptEx写的一个极小的服务端程序.由于刚刚接触ICOP加上本人刚毕业不到一年,所以里面 ...

最新文章

  1. element select 自动展开_原生js 让select下拉框自动展开 可用size 属性来代替展开动作...
  2. 【C++】异常 Exception
  3. DROP TABLE、TRUNCATE TABLE和DELETE的区别
  4. Csv数据库CsvDb
  5. 长为N的数组,元素范围是0-N-1,其中只有一个数是重复的,找出这个重复元素...
  6. ASP.NET 中处理页面“回退”的方法
  7. JS流程图解决方案GoJS
  8. linux github代码仓库,centos7上使用git命令把代码放到github上
  9. java 蓝桥杯算法训练 水仙花(题解)
  10. HDP SandBox 安装与初步配置
  11. PHP-Header缓存策略
  12. MATLAB 字符串与矩阵的学习
  13. 若依前后端分离密码修改成功,登录提示用户名或密码不正确。
  14. ESXi 6.7 封装驱动(Intel-I219V使用非vib的离线包驱动格式)
  15. 云边协同的智能制造系统
  16. 如何查看vue打印的console.log日志
  17. Apple developer新的的注册方式
  18. d2lzh_pytorch的安装
  19. 11个问题,帮你彻底搞懂工业互联网
  20. bim考证会监控到电脑屏幕吗

热门文章

  1. 双11小黑盒很炫酷?咱们用CSS变量来改进一下!
  2. 实现UC浏览器启动应用时引导用户开启存储空间权限
  3. CF 853A Planning
  4. 网红的根源是屌丝逆袭
  5. android 渐变蒙版_Android实现遮罩层(蒙板)效果
  6. P2P技术详解(三):P2P技术之STUN、TURN、ICE详解
  7. dp交换机命令_华为交换机配置命令详解
  8. UESTC 1253 阿里巴巴和n个大盗(博弈)
  9. 上交大网安研究研究方向介绍
  10. BootLoader基础详解