正文

IOCP配合AcceptEx的例子(2)2006-07-02 14:36:00

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

分享到:

这是在学《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

阅读(10089) | 评论(2)


版权声明:编程爱好者网站为此博客服务提供商,如本文牵涉到版权问题,编程爱好者网站不承担相关责任,如有版权问题请直接与本文作者联系解决。谢谢!

评论

loading...
您需要登录后才能评论,请 登录 或者 注册