首页
社区
课程
招聘
[求助]IO完成端口遇到的问题
发表于: 2013-10-12 15:22 5179

[求助]IO完成端口遇到的问题

2013-10-12 15:22
5179
有中文的地文,表示没明白的,求解释

//Worker thread will service IOCP requests
DWORD WINAPI WorkerThread(LPVOID lpParam)
{   
        int nThreadNo = (int)lpParam;

        void *lpContext = NULL;
        OVERLAPPED       *pOverlapped = NULL;
        CClientContext   *pClientContext = NULL;
        DWORD            dwBytesTransfered = 0;
        int nBytesRecv = 0;
        int nBytesSent = 0;
        DWORD             dwBytes = 0, dwFlags = 0;

        //Worker thread will be around to process requests, until a Shutdown event is not Signaled.
        while (WAIT_OBJECT_0 != WaitForSingleObject(g_hShutdownEvent, 0))
        {
                BOOL bReturn = GetQueuedCompletionStatus(
                        g_hIOCompletionPort,
                        &dwBytesTransfered,
                        (LPDWORD)&lpContext,
                        &pOverlapped,
                        INFINITE);

                if (NULL == lpContext)
                {
                        //We are shutting down
                        break;
                }
                //Get the client context
                pClientContext = (CClientContext *)lpContext;
                if ((FALSE == bReturn) || ((TRUE == bReturn) && (0 == dwBytesTransfered)))
                {
                        //Client connection gone, remove it.
                        RemoveFromClientListAndFreeMemory(pClientContext);
                        continue;
                }
                WSABUF *p_wbuf = pClientContext->GetWSABUFPtr();
                OVERLAPPED *p_ol = pClientContext->GetOVERLAPPEDPtr();

                switch (pClientContext->GetOpCode())
                {
                case OP_READ:  //#define 0,定义为0,

                        pClientContext->IncrSentBytes(dwBytesTransfered);

                        //Write operation was finished, see if all the data was sent.
                        //Else post another write.
                        if(pClientContext->GetSentBytes() < pClientContext->GetTotalBytes())
                        {
                                pClientContext->SetOpCode(OP_READ);

                                p_wbuf->buf += pClientContext->GetSentBytes();
                                p_wbuf->len = pClientContext->GetTotalBytes() - pClientContext->GetSentBytes();

                                dwFlags = 0;

                                //Overlapped send
                                nBytesSent = WSASend(pClientContext->GetSocket(), p_wbuf, 1,
                                        &dwBytes, dwFlags, p_ol, NULL);

                                if ((SOCKET_ERROR == nBytesSent) && (WSA_IO_PENDING != WSAGetLastError()))
                                {
                                        //Let's not work with this client
                                        RemoveFromClientListAndFreeMemory(pClientContext);
                                }
                        }
                        else //上面是因为没有发送完,这儿已经发送完成了,为什么要投递WSARecv呢,没看明白
                        {
                                //Once the data is successfully received, we will print it.
                                pClientContext->SetOpCode(OP_WRITE);
                                pClientContext->ResetWSABUF();

                                dwFlags = 0;

                                //Get the data.
                                nBytesRecv = WSARecv(pClientContext->GetSocket(), p_wbuf, 1,
                                        &dwBytes, &dwFlags, p_ol, NULL);

                                if ((SOCKET_ERROR == nBytesRecv) && (WSA_IO_PENDING != WSAGetLastError()))
                                {
                                        WriteToConsole("\nThread %d: Error occurred while executing WSARecv().", nThreadNo);

                                        //Let's not work with this client
                                        RemoveFromClientListAndFreeMemory(pClientContext);
                                }
                        }

                        break;

                case OP_WRITE:  //#define  1,定义为1,这儿到底是什么意思。是说有数据到了吗?还是说要发送数据?
                        //没看懂,求解释,后面也有一个WSASend,这个是返回数据?如果不需要返回数据,读取数据应该怎么弄,是不是说数据已经在szBuffer里面了,
                        //
                        char szBuffer[MAX_BUFFER_LEN];

                        //Display the message we recevied
                        pClientContext->GetBuffer(szBuffer);

                        WriteToConsole("\nThread %d: The following message was received: %s", nThreadNo, szBuffer);

                        //Send the message back to the client.
                        pClientContext->SetOpCode(OP_READ);

                        pClientContext->SetTotalBytes(dwBytesTransfered);
                        pClientContext->SetSentBytes(0);

                        p_wbuf->len  = dwBytesTransfered;

                        dwFlags = 0;

                        //Overlapped send
                        nBytesSent = WSASend(pClientContext->GetSocket(), p_wbuf, 1,
                                &dwBytes, dwFlags, p_ol, NULL);

                        if ((SOCKET_ERROR == nBytesSent) && (WSA_IO_PENDING != WSAGetLastError()))
                        {
                                WriteToConsole("\nThread %d: Error occurred while executing WSASend().", nThreadNo);

                                //Let's not work with this client
                                RemoveFromClientListAndFreeMemory(pClientContext);
                        }

                        break;

                default:
                        //We should never be reaching here, under normal circumstances.
                        break;
                } // switch
        } // while

        return 0;
}

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 0
支持
分享
最新回复 (4)
雪    币: 110
活跃值: (527)
能力值: ( LV4,RANK:40 )
在线值:
发帖
回帖
粉丝
2
我一直没明白,OPREAD,OPWRITE有什么区别。。
2013-10-12 15:24
0
雪    币: 209
活跃值: (143)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
OPREAD,OPWRITE都是用户定义的,收到它们就可以知道是什么操作完成了,然后做针对性处理
2013-10-12 16:01
0
雪    币: 228
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
你应该连最基本的异步过程的实现方式还没弄清,要理解这里很有难度;更何况这里的代码定义有点“左”。

//Get the client context
pClientContext = (CClientContext *)lpContext; //这里是异步过程执行时所用的“上下文”,或者说是执行环境。可以多去了解一下 “回调”、“闭包” 等概念;

上面的 pClientContext  从哪里来的:

        pClientContext->SetOpCode(OP_READ);

        p_wbuf->buf += pClientContext->GetSentBytes();
        p_wbuf->len = pClientContext->GetTotalBytes() - pClientContext->GetSentBytes();

        dwFlags = 0;

        //Overlapped send
        nBytesSent = WSASend(pClientContext->GetSocket(), p_wbuf, 1,
          &dwBytes, dwFlags, p_ol, NULL);

以上代码 执行就是  向系统发起一次异步 IO 操作,pClientContext 通过 p_ol 被系统记录到与本次的发起动作相关的记录之中(绑定到了此 IO操作上),当有线程 调用 GetQueuedCompletionStatus 时,如果此 IO 操作已经完成或者失败,那么 GetQueuedCompletionStatus  会返回相关的相关的信息,同时返回的还有发起 IO 时 绑定的 pClientContext 。所以只要查看一下当初发起 IO 操作时,记录在  pClientContext 中的OpCode (  pClientContext->SetOpCode() 与 pClientContext->GetOpCode()  )是什么,就能知道本次返回的是 什么 IO;所以这里 OP_WRITE \ OP_READ 是自定义的,系统不解释。

如果不清楚 系统是怎么通过 p_ol 将 pClientContext 与 IO 操作绑定在一起 并且在适当的时候返回的,那么RTFM!

else //上面是因为没有发送完,这儿已经发送完成了,为什么要投递WSARecv呢,没看明白

向client 回发的包发送完了,那么投递 WSARecv 接收下一个 client 发过来的包
2013-10-12 16:52
0
雪    币: 257
活跃值: (67)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
5
路过,来看一下
2013-10-12 18:14
0
游客
登录 | 注册 方可回帖
返回
//