网络学习杂七杂八

一些杂七杂八的测试代码就放这里了 做个索引记录

1 IOCP

从windows网络编程 第八章 获取的C语言版本代码

如果想学习 可以搜搜 “ 小猪 PIGGYXP iocp” “windows网络编程 iocp ” 应该有所收获

自己从头写了一遍c++ 以便加深记忆 

#pragma once
#include "WSAManager.h"
#include "windows.h"
#include <thread>
#include <vector>

const int defaultPortNum = 8893;
const int defaultThreadNum = 1;

#define CLOSEHANDLE(x) if(NULL != (x) && INVALID_HANDLE_VALUE != (x) ){CloseHandle(x);x = NULL;}
#define CLOSESOCKET(x) if(INVALID_SOCKET != (x)){closesocket(x);x = INVALID_SOCKET;}


const int defaultBufSize = 8192;

typedef struct
{
    OVERLAPPED Overlapped;
    WSABUF DataBuf;
    CHAR Buffer[defaultBufSize];
    DWORD BytesSEND;
    DWORD BytesRECV;
} PER_IO_OPERATION_DATA, *LPPER_IO_OPERATION_DATA;


typedef struct
{
    SOCKET Socket;
} PER_HANDLE_DATA, *LPPER_HANDLE_DATA;


class IOCPModel {
public:
    IOCPModel(int portNum = defaultPortNum):
        completionPort_(NULL),
        threadNum_(defaultThreadNum),
        pthrArray_(NULL),
        listenSock_(INVALID_SOCKET),
        thrExitFlag_(true)
    {
        portNum_ = portNum;
    }

    ~IOCPModel()
    {
        StopThread();
        CLOSEHANDLE(completionPort_);
        CLOSESOCKET(listenSock_);
    }

    bool Start();
    bool Init();
    bool ServerWorkerThread(void* CompletionPortID);
    bool StartThread(int thrNum = defaultThreadNum);
    bool StopThread();
    bool ListenBindOrDie();
    bool AcceptPostSocket();
    void DeleteHandleData(PER_HANDLE_DATA* PerHandleData);
    void DeleteIoData(PER_IO_OPERATION_DATA* PerIoData);
private:
    std::vector<PER_HANDLE_DATA*> perHandleDataVec_;
    std::vector<PER_IO_OPERATION_DATA*> perIOOperationDataVec_;
    WSAManager wsaManager_;
    HANDLE completionPort_;
    int portNum_;
    std::thread* pthrArray_;
    int threadNum_;
    bool thrExitFlag_;
    SOCKET listenSock_;
};
View Code
#pragma once
#include "IocpModel.h"
#include <iomanip>

bool IOCPModel::AcceptPostSocket()
{
    SOCKET acceptSock;

    if ((acceptSock = WSAAccept(listenSock_, NULL, NULL, NULL, 0)) == SOCKET_ERROR)
    {
        std::cerr << "WSAAccept() failed with error " << WSAGetLastError() << std::endl;
        return false;
    }

    PER_HANDLE_DATA* pHandleData = new PER_HANDLE_DATA;
    if (NULL == pHandleData)
    {
        std::cerr << __FUNCTION__ <<  ".  PER_HANDLE_DATA malloc failed" << std::endl;
        return false;
    }
    pHandleData->Socket = acceptSock;
    perHandleDataVec_.push_back(pHandleData);

    if ( CreateIoCompletionPort((HANDLE)acceptSock, completionPort_, (ULONG_PTR)pHandleData, 0) 
        == NULL)
    {
        std::cerr << __FUNCTION__ << ".  CreateIoCompletionPort  failed" << std::endl;
        return false;
    }

    PER_IO_OPERATION_DATA* PerIoData = new PER_IO_OPERATION_DATA;
    if (NULL == PerIoData)
    {
        std::cerr << __FUNCTION__ << ".  PER_IO_OPERATEION_DATA malloc failed" << std::endl;
        return false;
    }
    ZeroMemory(&(PerIoData->Overlapped), sizeof(OVERLAPPED));
    PerIoData->BytesSEND = 0;
    PerIoData->BytesRECV = 0;
    PerIoData->DataBuf.len = defaultBufSize;
    PerIoData->DataBuf.buf = PerIoData->Buffer;

    perIOOperationDataVec_.push_back(PerIoData);
    DWORD Flags = 0;
    DWORD RecvBytes = 0;
    if (WSARecv(acceptSock, &(PerIoData->DataBuf), 1, &RecvBytes, &Flags,
        &(PerIoData->Overlapped), NULL) == SOCKET_ERROR)
    {
        if (WSAGetLastError() != ERROR_IO_PENDING)
        {
            std::cerr << __FUNCTION__ << ".  WSARecv() failed with error " << WSAGetLastError() << std::endl;
            return false;
        }
    }

    return true;
}

bool IOCPModel::Start()
{
    if (false == Init())
    {
        return false;
    }

    while (true)
    {
        if (false == AcceptPostSocket())
            break;
    }

    return true;
}
bool IOCPModel::StartThread(int thrNum )
{
    pthrArray_ = new std::thread[thrNum];
    if (NULL == pthrArray_)
    {
        std::cerr << "new thread error" << std::endl;
        return false;
    }
    
    thrExitFlag_ = false;
    threadNum_ = thrNum;
    for (int i = 0; i < threadNum_; i++)
    {
        pthrArray_[i] = std::thread(&IOCPModel::ServerWorkerThread, this, completionPort_);
    }

    return true;
}


bool IOCPModel::StopThread()
{
    thrExitFlag_ = true;
    for (int i = 0; i < threadNum_; i++)
    {
        pthrArray_[i].join();
    }

    if (NULL != pthrArray_)
    {
        delete[] pthrArray_;
    }
    return true;
}

bool IOCPModel::ListenBindOrDie()
{
    if ((listenSock_ = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0,
        WSA_FLAG_OVERLAPPED)) == INVALID_SOCKET)
    {
        std::cerr << __FUNCTION__ << ". Create listenSock_ failed  "<< std::endl;
        return false;
    }
    SOCKADDR_IN InternetAddr;
    InternetAddr.sin_family = AF_INET;
    InternetAddr.sin_addr.s_addr = htonl(INADDR_ANY);
    InternetAddr.sin_port = htons(portNum_);

    if (bind(listenSock_, (PSOCKADDR)&InternetAddr, sizeof(InternetAddr)) == SOCKET_ERROR)
    {
        std::cerr << __FUNCTION__ << ". bind() failed with error  " << WSAGetLastError() << std::endl;
        return false;
    }

    if (listen(listenSock_, 5) == SOCKET_ERROR)
    {
        std::cerr << __FUNCTION__ << ". listen() failed with error  " << WSAGetLastError() << std::endl;
        return false;
    }

    return true;
}

bool IOCPModel::Init()
{
    if ( (completionPort_ =
        CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0)
         ) == NULL)
    {
        std::cerr << __FUNCTION__ <<  ". CreateIoCompletionPort failed with error:  " <<  GetLastError() << std::endl;
        return false ;
    }

    if (false == StartThread(1))
    {
        std::cerr << __FUNCTION__ << ". CreateIoCompletionPort failed with error:  " << GetLastError() << std::endl;
        return false;
    }

    if (false == ListenBindOrDie())
    {
        return false;
    }

    return true;
}

void IOCPModel::DeleteHandleData(PER_HANDLE_DATA* PerHandleData)
{
    // todo 
    delete PerHandleData;
}


void IOCPModel::DeleteIoData(PER_IO_OPERATION_DATA* PerIoData)
{
    //todo
    delete PerIoData;
}




bool IOCPModel::ServerWorkerThread(void* completionPortID)
{
    HANDLE CompletionPort = (HANDLE)completionPortID;
    DWORD BytesTransferred;
    //LPOVERLAPPED Overlapped;
    LPPER_HANDLE_DATA PerHandleData;
    LPPER_IO_OPERATION_DATA PerIoData;
    DWORD SendBytes, RecvBytes;
    DWORD Flags;

    while (!thrExitFlag_)
    {
        if (GetQueuedCompletionStatus(CompletionPort, &BytesTransferred,
            (LPDWORD)&PerHandleData, (LPOVERLAPPED *)&PerIoData, INFINITE) == 0)
        {
            std::cerr << __FUNCTION__ << ". GetQueuedCompletionStatus failed with error"
                << GetLastError() << std::endl;
            return false;
        }

        if (0 == BytesTransferred)
        {
            std::cerr << "close socket " << PerHandleData->Socket << std::endl;
            CLOSESOCKET(PerHandleData->Socket);

            DeleteHandleData(PerHandleData);
            DeleteIoData(PerIoData);
            continue;
        }

        // only for test
        {
            //再次投递
            Flags = 0;
            ZeroMemory(&(PerIoData->Overlapped), sizeof(OVERLAPPED));

            PerIoData->DataBuf.len = defaultBufSize;
            PerIoData->DataBuf.buf = PerIoData->Buffer;
            std::cout << std::setw(BytesTransferred) << PerIoData->DataBuf.buf << std::endl;

            if (WSARecv(PerHandleData->Socket, &(PerIoData->DataBuf), 1, &RecvBytes, &Flags,
                &(PerIoData->Overlapped), NULL) == SOCKET_ERROR)
            {
                if (WSAGetLastError() != ERROR_IO_PENDING)
                {
                    printf("WSARecv() failed with error %d\n", WSAGetLastError());
                    return 0;
                }
            }


        }

        /*
        if (PerIoData->BytesRECV == 0)
        {
            PerIoData->BytesRECV = BytesTransferred;
            PerIoData->BytesSEND = 0;
        }
        else
        {
            PerIoData->BytesSEND += BytesTransferred;
        }

        if (PerIoData->BytesRECV > PerIoData->BytesSEND)
        {

            // Post another WSASend() request.
            // Since WSASend() is not gauranteed to send all of the bytes requested,
            // continue posting WSASend() calls until all received bytes are sent.

            ZeroMemory(&(PerIoData->Overlapped), sizeof(OVERLAPPED));

            PerIoData->DataBuf.buf = PerIoData->Buffer + PerIoData->BytesSEND;
            PerIoData->DataBuf.len = PerIoData->BytesRECV - PerIoData->BytesSEND;

            if (WSASend(PerHandleData->Socket, &(PerIoData->DataBuf), 1, &SendBytes, 0,
                &(PerIoData->Overlapped), NULL) == SOCKET_ERROR)
            {
                if (WSAGetLastError() != ERROR_IO_PENDING)
                {
                    printf("WSASend() failed with error %d\n", WSAGetLastError());
                    return 0;
                }
            }
        }
        else
        {
            PerIoData->BytesRECV = 0;

            // Now that there are no more bytes to send post another WSARecv() request.

            Flags = 0;
            ZeroMemory(&(PerIoData->Overlapped), sizeof(OVERLAPPED));

            PerIoData->DataBuf.len = defaultBufSize;
            PerIoData->DataBuf.buf = PerIoData->Buffer;

            if (WSARecv(PerHandleData->Socket, &(PerIoData->DataBuf), 1, &RecvBytes, &Flags,
                &(PerIoData->Overlapped), NULL) == SOCKET_ERROR)
            {
                if (WSAGetLastError() != ERROR_IO_PENDING)
                {
                    printf("WSARecv() failed with error %d\n", WSAGetLastError());
                    return 0;
                }
            }
        }
        */


    }




    return true;
}
View Code
// MyIocp.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include "IocpModel.h"


int main()
{
    IOCPModel iocpServer(8892);
    iocpServer.Start();

    IOCPModel iocpServer_another;
    iocpServer_another.Start();

    return 0;
}

2 待续.......

原文地址:https://www.cnblogs.com/itdef/p/5396174.html