C++ IOCP的内存使用

C++ IOCP的内存使用,c++,windows,iocp,C++,Windows,Iocp,我将我们的代码转换为使用IOCP,通信相对稳定,但应用程序的内存使用正在增加。看起来我(在完成函数调用时)得到的OverlappedEx对象比我创建的要少得多。我的代码如下。我做错了什么 #ifndef NETWORK_DATA #define NETWORK_DATA #include <afxwin.h> #include <vector> #include <string> #include "CriticalSectionLocker.h" usi

我将我们的代码转换为使用IOCP,通信相对稳定,但应用程序的内存使用正在增加。看起来我(在完成函数调用时)得到的OverlappedEx对象比我创建的要少得多。我的代码如下。我做错了什么

#ifndef NETWORK_DATA
#define NETWORK_DATA

#include <afxwin.h>
#include <vector>
#include <string>
#include "CriticalSectionLocker.h"

using namespace std;

DWORD NetworkManager::NetworkThread(void* param)
{
    bool bRun = true;


    while (bRun)
    {
        DWORD wait = ::WaitForSingleObject(CCommunicationManager::s_hShutdownEvent, 0);
        if (WAIT_OBJECT_0 == wait)
        {
            bRun = false;
            DEBUG_LOG0("Shutdown event was signalled thread");
        }
        else
        {
            DWORD dwBytesTransfered = 0;
            void* lpContext = nullptr;
            OVERLAPPED* pOverlapped = nullptr;

            BOOL bReturn = GetQueuedCompletionStatus(s_IOCompletionPort,
                                                    &dwBytesTransfered,
                                                    (LPDWORD)&lpContext,
                                                    &pOverlapped,
                                                    INFINITE);
            if (nullptr == lpContext)
            {
                DEBUG_LOG0("invalid context");
                /*continue;*/
            }
            else
            {
                if (bReturn && dwBytesTransfered > 0)
                {
                    OverlappedEx* data = reinterpret_cast<OverlappedEx*>(pOverlapped);
                    ServerData* networkData = reinterpret_cast<ServerData*>(lpContext);

                    if (networkData && data)
                    {                       
                        switch(data->m_opType)
                        {
                        case OverlappedEx::OP_READ:
                                /*DEBUG_LOG4("device name: %s bytes received: %d socket: %d handle: %d", 
                                    networkData->Name().c_str(), dwBytesTransfered, networkData->Socket(), networkData->Handle());*/
                                networkData->CompleteReceive(dwBytesTransfered, data);                              
                                break;
                            case OverlappedEx::OP_WRITE:
                                /*DEBUG_LOG4("device name: %s bytes sent: %d socket: %d handle: %d",
                                    networkData->Name().c_str(), dwBytesTransfered, networkData->Socket(), networkData->Handle());*/
                                networkData->CompleteSend(dwBytesTransfered, data);
                                break;
                        }
                    }
                }
                else
                {
                    /*DEBUG_LOG2("GetQueuedCompletionStatus failed: bReturn: %d dwBytesTransferred: %u", bReturn, dwBytesTransfered);*/
                }
            }
        }
    }
    return 0;
}


enum NetworkType
{
    UDP,
    TCP
};

struct OverlappedEx : public OVERLAPPED
{
    enum OperationType
    {
        OP_READ,
        OP_WRITE
    };  

    const static int MAX_PACKET_SIZE = 2048;
    WSABUF m_wBuf;
    char m_buffer[MAX_PACKET_SIZE];
    OperationType m_opType; 

    OverlappedEx()
    {       
        Clear();
        m_refCount = 1;
    }

    void AddRef()
    {
        ::InterlockedIncrement(&m_refCount);
    }

    void Release()
    {
        ::InterlockedDecrement(&m_refCount);
    }

    int Refcount() const
    {       
        return InterlockedExchangeAdd((unsigned long*)&m_refCount, 0UL);
    }

    ~OverlappedEx()
    {       
        Clear();        
    }

    void Clear()
    {
        memset(m_buffer, 0, MAX_PACKET_SIZE);
        m_wBuf.buf = m_buffer;
        m_wBuf.len = MAX_PACKET_SIZE;
        Internal = 0;
        InternalHigh = 0;
        Offset = 0;
        OffsetHigh = 0;
        hEvent = nullptr;
        m_opType = OP_READ;
    }

private:
    volatile LONG m_refCount;
};


class ServerData
{       
public:
    const static int MAX_REVEIVE_QUEUE_SIZE = 100;
    const static int MAX_PACKET_SIZE = 2048;
    const static int MAX_SEND_QUEUE_SIZE = 10;
    const static int MAX_RECEIVE_QUEUE_SIZE = 100;  
    const static int MAX_OVERLAPPED_STRUCTS = 20;   


    ServerData(NetworkType netType, const string& sName, CCommunicationManager::CommHandle handle,
                            SOCKET sock, HANDLE IOPort) :   
        m_sName(sName)
    {
        InitializeCriticalSection(&m_receiveQueLock);
        InitializeCriticalSection(&m_objectLock);
        m_Handle = handle;
        m_Socket = sock;
        m_nIPAddress = 0;           
        m_netType = netType;
        m_bEnabled = true;
        m_ovlpIndex = 0;

        for (int i = 0; i < MAX_OVERLAPPED_STRUCTS; ++i)
        {
            m_olps.push_back(new OverlappedEx);
        }

        /* Associate socket with completion handle */
        if (m_Socket != 0)
        {
            CreateIoCompletionPort( reinterpret_cast<HANDLE>(m_Socket), IOPort, reinterpret_cast<ULONG_PTR>(this), 0 );
        }
    }       

    ~ServerData()
    {           
        CriticalSectionLocker lock(&m_receiveQueLock);
        DeleteCriticalSection(&m_receiveQueLock);

        DeleteCriticalSection(&m_objectLock);
        closesocket(m_Socket);  
    }

    const string& Name() const { return m_sName; }
    bool Enabled() const { return m_bEnabled; }
    void SetEnabled(bool bEnabled)
    {
        m_bEnabled = bEnabled;
    }

    int Handle() const { return m_Handle; }
    void SetHandle(int handle)
    {
        m_Handle = handle;
    }

    unsigned long IPAddress() const { return m_nIPAddress; }

    SOCKET Socket() const
    {
        return m_Socket;
    }

    void SetSocket(SOCKET sock)
    {
        m_Socket = sock;
    }

    void SetIPAddress(unsigned long nIP)
    {
        m_nIPAddress = nIP;
    }       

    bool ValidTelegram(const vector<char>& telegram) const
    {
        return false;
    }

    OverlappedEx* GetBuffer()
    {
        OverlappedEx* ret = nullptr;

        if (!m_olps.empty())
        {
            ret = m_olps.front();
            m_olps.pop_front();
        }

        return ret;
    }


    void CompleteReceive(size_t numBytes, OverlappedEx* data)
    {       
        //DEBUG_LOG1("%d buffers are available", AvailableBufferCount());

        if (numBytes > 0)
        {   
            vector<char> v(data->m_buffer, data->m_buffer + numBytes);          
            ReceivedData rd;
            rd.SetData(v);
            EnqueReceiveMessage(rd);    
        }   

        data->Release();
        {
            CriticalSectionLocker lock(&m_objectLock);
            m_olps.push_back(data);
//          DEBUG_LOG1("Queue size: %d", m_olps.size());
        }

        StartReceiving();

    }

    void CompleteSend(size_t numBytes, OverlappedEx* data)
    {

        data->Release();    
        {
            CriticalSectionLocker lock(&m_objectLock);
            m_olps.push_back(data);
            //DEBUG_LOG1("Queue size: %d", m_olps.size());
        }

        //DEBUG_LOG2("Object: %s num sent: %d", Name().c_str(), numBytes);
    }

    void StartReceiving()
    {
        DWORD bytesRecv = 0;
        sockaddr_in senderAddr;
        DWORD flags = 0;
        int senderAddrSize = sizeof(senderAddr);
        int rc = 0;

        CriticalSectionLocker lock(&m_objectLock);
        auto olp = GetBuffer();
        if (!olp)
        {       
            if (...)
            {
                m_olps.push_back(new OverlappedEx);
                olp = GetBuffer();
            }
            else
            {
                if (...)
                {
                    DEBUG_LOG1("Name: %s ************* NO AVAILABLE BUFFERS - bailing ***************", Name().c_str());
                }
                return;
            }
        }

        olp->Clear();
        olp->m_opType = OverlappedEx::OP_READ;
        olp->AddRef();

        switch(GetNetworkType())
        {
        case UDP:
            {
                rc = WSARecvFrom(Socket(),
                                &olp->m_wBuf,
                                1,
                                &bytesRecv,
                                &flags,
                                (SOCKADDR *)&senderAddr,
                                &senderAddrSize, (OVERLAPPED*)olp, NULL);
            }
            break;
        case TCP:
            {
                rc = WSARecv(Socket(), 
                            &olp->m_wBuf,
                            1, 
                            &bytesRecv, 
                            &flags, 
                            (OVERLAPPED*)olp, NULL);
            }
            break;
        }

        if (SOCKET_ERROR == rc)
        {
            DWORD err = WSAGetLastError();
            if (err != WSA_IO_PENDING)
            {
                olp->Release();
                m_olps.push_back(olp);
            }
        }
    }


    void SetWriteBuf(const SendData& msg, OverlappedEx* data)
    {
        int len = min(msg.Data().size(), MAX_PACKET_SIZE);
        memcpy(data->m_buffer, &msg.Data()[0], len);
        data->m_wBuf.buf = data->m_buffer;
        data->m_wBuf.len = len;
    }

    void StartSending(const SendData& msg)
    {

        DEBUG_LOG1("device name: %s", Name().c_str());

        int rc = 0;
        DWORD bytesSent = 0;
        DWORD flags = 0;    
        SOCKET sock = Socket();

        int addrSize = sizeof(sockaddr_in);     

        CriticalSectionLocker lock(&m_objectLock);
        //UpdateOverlapped(OverlappedEx::OP_WRITE);

        auto olp = GetBuffer();
        if (!olp)
        {
            if (...)
            {
                m_olps.push_back(new OverlappedEx);
                olp = GetBuffer();
                DEBUG_LOG2("name: %s ************* NO AVAILABLE BUFFERS new size: %d ***************", Name().c_str(), m_olps.size());
            }
            else
            {
                if (...)
                {
                    DEBUG_LOG1("Name: %s ************* NO AVAILABLE BUFFERS - bailing ***************", Name().c_str());
                }
                return;
            }
        }

        olp->Clear();
        olp->m_opType = OverlappedEx::OP_WRITE;
        olp->AddRef();
        SetWriteBuf(msg, olp);

        switch(GetNetworkType())
        {
        case UDP:

            rc = WSASendTo(Socket(), &olp->m_wBuf, 1,
                            &bytesSent, flags, (sockaddr*)&msg.SendAddress(),
                            addrSize, (OVERLAPPED*)olp, NULL);
            break;
        case TCP:

            rc = WSASend(Socket(), &olp->m_wBuf, 1,
                        &bytesSent, flags, (OVERLAPPED*)olp, NULL);
            break;
        }

        if (SOCKET_ERROR == rc)
        {
            DWORD err = WSAGetLastError();
            if (err != WSA_IO_PENDING)
            {
                olp->Release();
                m_olps.push_back(olp);
            }
        }
    }

    size_t ReceiveQueueSize()
    {
        CriticalSectionLocker lock(&m_receiveQueLock);
        return m_receiveDataQueue.size();
    }

    void GetAllData(vector <ReceivedData> & data)
    {
        CriticalSectionLocker lock(&m_receiveQueLock);
        while (m_receiveDataQueue.size() > 0)
        {
            data.push_back(m_receiveDataQueue.front());
            m_receiveDataQueue.pop_front();
        }
    }

    void DequeReceiveMessage(ReceivedData& msg)
    {
        CriticalSectionLocker lock(&m_receiveQueLock);
        if (m_receiveDataQueue.size() > 0)
        {
            msg = m_receiveDataQueue.front();
            m_receiveDataQueue.pop_front();
        }
    }

    template <class T>
    void EnqueReceiveMessage(T&& data)
    {
        CriticalSectionLocker lock(&m_receiveQueLock);
        if (m_receiveDataQueue.size() <= MAX_RECEIVE_QUEUE_SIZE)
        {
            m_receiveDataQueue.push_back(data);
        }
        else
        {
            static int s_nLogCount = 0;
            if (s_nLogCount % 100 == 0)
            {
                DEBUG_LOG2("Max queue size was reached handle id: %d in %s", Handle(), Name().c_str());
            }
            s_nLogCount++;
        }
    }           

    NetworkType GetNetworkType() const
    {
        return m_netType;
    }   

private:        
    ServerData(const ServerData&);
    ServerData& operator=(const ServerData&);
private:
    bool m_bEnabled;                                                            //!< This member flags if this reciever is enabled for receiving incoming connections.
    int m_Handle;                                                   //!< This member holds the handle for this receiver.
    SOCKET m_Socket;                                                        //!< This member holds the socket information for this receiver.        
    unsigned long m_nIPAddress;                                             //!< This member holds an IP address the socket is bound to.
    deque < ReceivedData > m_receiveDataQueue;
    CRITICAL_SECTION m_receiveQueLock;  
    CRITICAL_SECTION m_objectLock;
    string m_sName; 
    NetworkType m_netType;
    deque<OverlappedEx*> m_olps;
    size_t m_ovlpIndex;
};


#endif
\ifndef网络数据
#定义网络数据
#包括
#包括
#包括
#包括“CriticalSectionLocker.h”
使用名称空间std;
DWORD NetworkManager::NetworkThread(void*param)
{
布尔布伦=真;
while(bRun)
{
DWORD wait=::WaitForSingleObject(CCommunicationManager::ShshutdownEvent,0);
if(WAIT_OBJECT_0==WAIT)
{
bRun=假;
DEBUG_LOG0(“向线程发送关闭事件信号”);
}
其他的
{
DWORD DWBYTESTTRANSFERED=0;
void*lpContext=nullptr;
重叠*pOverlapped=nullptr;
BOOL bReturn=GetQueuedCompletionStatus(s_IOCompletionPort,
&DwByTestTransfer,
(LPDWORD)和lpContext,
&波弗雷普,
无限);
if(nullptr==lpContext)
{
调试日志0(“无效上下文”);
/*继续*/
}
其他的
{
if(bReturn&dwbytesttransfered>0)
{
OverlappedEx*数据=重新解释铸件(pOverlapped);
ServerData*networkData=reinterpret\u cast(lpContext);
if(网络数据和数据)
{                       
开关(数据->m_操作类型)
{
案例X::OP_读取:
/*调试日志4(“设备名称:%s接收字节:%d套接字:%d句柄:%d”,
networkData->Name().c_str(),dwbytesttransfered,networkData->Socket(),networkData->Handle()*/
networkData->CompleteReceive(DWByTestTransfered,数据);
打破
案例X::OP_WRITE:
/*调试日志4(“设备名称:%s已发送字节:%d套接字:%d句柄:%d”,
networkData->Name().c_str(),dwbytesttransfered,networkData->Socket(),networkData->Handle()*/
networkData->CompleteSend(DWByTestTransfered,数据);
打破
}
}
}
其他的
{
/*调试日志2(“GetQueuedCompletionStatus失败:返回:%d DwByTestTransfered:%u”,返回,DwByTestTransfered)*/
}
}
}
}
返回0;
}
枚举网络类型
{
UDP,
传输控制协议
};
结构重叠pedex:公共重叠
{
枚举操作类型
{
OP_READ,
OP_WRITE
};  
const static int MAX_PACKET_SIZE=2048;
WSABUF m_wBuf;
字符m_缓冲区[最大数据包大小];
操作类型m_opType;
()
{       
清除();
m_refCount=1;
}
void AddRef()
{
::联锁增量(&m_refCount);
}
无效释放()
{
::联锁减量(&m_refCount);
}
int Refcount()常量
{       
返回InterlocatedExchangeAdd((无符号长*)&m_refCount,0UL);
}
~x()
{       
清除();
}
无效清除()
{
memset(m_缓冲区,0,最大数据包大小);
m_wBuf.buf=m_缓冲区;
m_wBuf.len=最大数据包大小;
内部=0;
内部高=0;
偏移量=0;
OffsetHigh=0;
hEvent=nullptr;
m_opType=OP_READ;
}
私人:
挥发性长m_参考计数;
};
类服务器数据
{       
公众:
const static int MAX_revive_QUEUE_SIZE=100;
const static int MAX_PACKET_SIZE=2048;
const static int MAX_SEND_QUEUE_SIZE=10;
const static int MAX_RECEIVE_QUEUE_SIZE=100;
const static int MAX_OVERLAPPED_STRUCTS=20;
ServerData(网络类型netType、常量字符串和sName、CCommunicationManager::CommHandle、,
插座插座、手柄(端口):
m_sName(sName)
{
初始化关键部分(&m_receiveQueLock);
初始化CriticalSection(&m_objectLock);
m_Handle=手柄;
m_插座=袜子;
m_nIPAddress=0;
m_netType=netType;
m_bEnabled=真;
m_ovlpIndex=0;
对于(int i=0;ivoid Release()
{
    if (!InterlockedDecrement(&m_refCount)) delete this;
}
OverlappedEx* data = static_cast<OverlappedEx*>(pOverlapped);
            olp->Release();
            m_olps.push_back(olp);