美文网首页
IO完成端口

IO完成端口

作者: szn好色仙人 | 来源:发表于2018-07-09 21:52 被阅读0次
    #include <WS2tcpip.h>
    #include <windows.h>
    #include <mswsock.h>
    #include <process.h>
    #include <stdio.h>
    #include <exception>
    
    
    using std::exception;
    
    
    #pragma comment(lib, "ws2_32")
    #pragma comment(lib, "mswsock")
    
    
    enum EIoType
    {
        eIoType_Send,
        eIoType_Recv
    };
    
    
    struct SIoContext
    {
        SIoContext() : sock(INVALID_SOCKET), eIoType(eIoType_Send)
        {
            memset(&OverLapped, 0, sizeof OverLapped);
            wsBuff.buf = buff;
            wsBuff.len = sizeof buff;
        }
    
        OVERLAPPED OverLapped;
        SOCKET sock;
        WSABUF wsBuff;
        char buff[65536];
        EIoType eIoType;
    };
    
    
    void InitNetEnvironment()
    {
        WSAData wsaData;
        if (0 == WSAStartup(MAKEWORD(2, 2), &wsaData)
            && wsaData.wVersion == 0x202)
        {
            return;
        }
    
        throw("网络初始化失败");
    }
    
    
    unsigned int __stdcall ThdDeal(void* pVoid);
    
    
    int main()
    {
        InitNetEnvironment();
    
        SOCKET sockSrv = socket(AF_INET, SOCK_STREAM, 0);
        if (INVALID_SOCKET == sockSrv)
        {
            throw(exception("监听套接字初始化失败"));
        }
    
        sockaddr_in sockAddr = {};
        sockAddr.sin_family = AF_INET;
        sockAddr.sin_port = htons(8000);
        if (1 != inet_pton(AF_INET, "192.168.0.51",
            &sockAddr.sin_addr.s_addr))
        {
            throw(exception("监听套接字地址初始化失败"));
    
        }
    
        if (SOCKET_ERROR == bind(sockSrv,
            reinterpret_cast<sockaddr*>(&sockAddr), sizeof sockaddr))
        {
            throw(exception("监听套接字bind失败"));
    
        }
    
        if (SOCKET_ERROR == listen(sockSrv, 100))
        {
            throw(exception("监听套接字listen失败"));
    
        }
    
        HANDLE hIoCmp = 
            CreateIoCompletionPort(INVALID_HANDLE_VALUE, nullptr, 0, 1);
        if (NULL == hIoCmp)
        {
            throw(exception("创建IO完成端口失败"));
        }
    
        for (int i = 0; i < 4; ++i)
        {
            CloseHandle(reinterpret_cast<HANDLE>
                (_beginthreadex(nullptr, 0, ThdDeal, hIoCmp, 0, nullptr)));
        }
    
        while (true)
        {
            SIoContext* pIoContext = new SIoContext();
    
            pIoContext->sock = accept(sockSrv, nullptr, nullptr);
            if (INVALID_SOCKET == pIoContext->sock)
            {
                throw(exception("创建套接字失败"));
            }
    
            CreateIoCompletionPort(reinterpret_cast<HANDLE>(pIoContext->sock),
                hIoCmp, reinterpret_cast<ULONG_PTR>(pIoContext), 0);
    
            DWORD nFlag = 0;
            pIoContext->eIoType = eIoType_Recv;
            WSARecv(pIoContext->sock, &pIoContext->wsBuff, 1, nullptr, &nFlag,
                &pIoContext->OverLapped, NULL);
        }
    
        return 0;
    }
    
    
    unsigned int __stdcall ThdDeal(void* pVoid)
    {
        HANDLE hIoCmp = static_cast<HANDLE>(pVoid);
    
        DWORD nSize = 0;
        ULONG_PTR nCmpKey = 0;
        LPOVERLAPPED pOverLapped = nullptr;
    
        while (true)
        {
            if (GetQueuedCompletionStatus(hIoCmp, &nSize, &nCmpKey,
                &pOverLapped, INFINITE))
            {
                SIoContext* pIoContext =
                    reinterpret_cast<SIoContext*>(nCmpKey);
    
                if (eIoType_Recv == pIoContext->eIoType)
                {
                    pIoContext->eIoType = eIoType_Send;
                    pIoContext->wsBuff.len = static_cast<unsigned long>
                        (pIoContext->OverLapped.InternalHigh);
    
                    if (pIoContext->wsBuff.len)
                    {
                        WSASend(pIoContext->sock, &pIoContext->wsBuff, 1,
                            nullptr, 0, &pIoContext->OverLapped, nullptr);
                    }
                    else
                    {
                        closesocket(pIoContext->sock);
                        delete pIoContext;
                    }
                }
                else
                {
                    printf("Same Data Send to Client, Continue To Recv\n");
    
                    DWORD nFlag = 0;
                    pIoContext->eIoType = eIoType_Recv;
                    pIoContext->wsBuff.len = sizeof pIoContext->buff;
                    WSARecv(pIoContext->sock, &pIoContext->wsBuff, 1, nullptr,
                        &nFlag, &pIoContext->OverLapped, NULL);
                }
            }
        }
    
        return 0;
    }
    

    相关文章

      网友评论

          本文标题:IO完成端口

          本文链接:https://www.haomeiwen.com/subject/vkhxpftx.html