当前位置:编程学习 > C#/ASP.NET >>

IOCP 自己学习尝试了好久。。。不明白。。。迷惑中

自己尝试实现了一段很小的IOCP模型。不过发现有内存泄漏。。。。按照网上说的用计数的方式实现的。。。。请各位同仁帮忙解释一下。。。。。。我自己确实真的找不出错误的地方了下面是自己的source。。。 --------------------编程问答-------------------- 什么都没有 --------------------编程问答-------------------- 内存泄漏事因为你new之后没delete,把new一个个查看一下,可以通过注释的方法慢慢找。 --------------------编程问答-------------------- server端



#include "stdafx.h"
#include <winsock2.h>
#include <stdio.h>
#include <map>
#include <iterator>

#define PORT 4999
#define BACKLOG 100
#define BUFFERLEN 20
#define CLOSE_SERVICE_NUM 0xFFFFFFFF

#pragma comment(lib, "ws2_32.lib")

using namespace std;

map<DWORD, LONGLONG> socketCount;

typedef struct _SOCKET_INFO_DATA
{
SOCKET sClient;
SOCKADDR_IN sClientAdd;
LONG id;
}SOCKET_INFO_DATA, *LP_SOCKET_INFO_DATA;

typedef struct _IO_OPERATION_DATA
{
WSAOVERLAPPED overLap;
WSABUF wsaBuffer;
DWORD recNumber;
DWORD flags;
}IO_OPERATION_DATA, *LP_IO_OPERATION_DATA;

CRITICAL_SECTION m_CriticalSection;

void HandleData(WSABUF);

void CloseResource(SYSTEM_INFO, HANDLE, SOCKET, HANDLE[]);

DWORD WINAPI ServerThread(LPVOID CompletionPortID);

void HandleData(WSABUF wasBuf)
{
//printf("%s", wasBuf.buf);
}
void CloseResource(SYSTEM_INFO systemInfo, HANDLE completionIo, SOCKET sService, HANDLE threadHandle[])
{
PostQueuedCompletionStatus(completionIo, CLOSE_SERVICE_NUM, 0, NULL);

for (int iCount = 0; iCount < systemInfo.dwNumberOfProcessors; iCount++)
{
CloseHandle(threadHandle[iCount]);
}

CloseHandle(completionIo);
closesocket(sService);
WSACleanup();
DeleteCriticalSection(&m_CriticalSection);
}
DWORD WINAPI ServerThread(LPVOID CompletionPortID)
{
HANDLE completionHandle = (HANDLE)CompletionPortID;
DWORD bytesTransferred;
DWORD errorInfo;
SOCKET_INFO_DATA socketInfo;
LP_SOCKET_INFO_DATA lpSocketStruct;
LP_IO_OPERATION_DATA lpOperationData;
BOOL bResult;

while (TRUE)
{
BOOL bResult = GetQueuedCompletionStatus(completionHandle, 
&bytesTransferred, (PULONG_PTR)&lpSocketStruct, 
(LPOVERLAPPED *)&lpOperationData, 
INFINITE); 

//EnterCriticalSection(&m_CriticalSection);

if (!bResult)
{
if (GetLastError() == WAIT_TIMEOUT);
{
//LeaveCriticalSection(&m_CriticalSection); 
continue;
}

if (lpOperationData != NULL)
{
EnterCriticalSection(&m_CriticalSection);

closesocket(lpSocketStruct->sClient);

delete lpOperationData->wsaBuffer.buf;
delete lpOperationData;
delete lpSocketStruct;
LeaveCriticalSection(&m_CriticalSection); 
}
continue;
}

int i = 0;

EnterCriticalSection(&m_CriticalSection);

DWORD lTemp = 0;

map<DWORD, LONGLONG>::iterator iterTemp;

iterTemp = socketCount.find((DWORD)lpSocketStruct);

if (iterTemp == socketCount.end())
{
LeaveCriticalSection(&m_CriticalSection);
continue;
}

lTemp = (LONGLONG)socketCount[(DWORD)lpSocketStruct];

if (bytesTransferred != 0)
{
lTemp++;

socketCount[(DWORD)lpSocketStruct] = lTemp;
}

if (bytesTransferred == CLOSE_SERVICE_NUM)
{
LeaveCriticalSection(&m_CriticalSection);

return 0;
}

DWORD dwordid = GetCurrentThreadId();

if (bytesTransferred == 0)
{
printf("bytesTransferred: %d \r\n", bytesTransferred);
if (lTemp == 0)
{
printf("SocketId: %d CloseThreadId: %d\r\n", lpSocketStruct->sClient, dwordid);
closesocket(lpSocketStruct->sClient);
delete lpOperationData->wsaBuffer.buf;
delete lpOperationData;
delete lpSocketStruct;

socketCount.erase(iterTemp);

LeaveCriticalSection(&m_CriticalSection);
continue;
}

lTemp--;

socketCount[(DWORD)lpSocketStruct] = lTemp;

LeaveCriticalSection(&m_CriticalSection);

WSARecv(lpSocketStruct->sClient, 
&lpOperationData->wsaBuffer, 
1, 
&lpOperationData->recNumber, 
&lpOperationData->flags, 
&lpOperationData->overLap,
NULL);

continue;
}

//HandleData(lpOperationData->wsaBuffer);

printf("SocketId: %d, ThreadId: %d, BufData: %c\r\n", lpSocketStruct->sClient, dwordid, lpOperationData->wsaBuffer.buf);

lTemp--;

socketCount[lpSocketStruct->sClient] = lTemp;

LeaveCriticalSection(&m_CriticalSection);

WSARecv(lpSocketStruct->sClient, 
&lpOperationData->wsaBuffer, 
1, 
&lpOperationData->recNumber, 
&lpOperationData->flags, 
&lpOperationData->overLap,
NULL);
}

return 0;
}

int _tmain(int argc, _TCHAR* argv[])
{
InitializeCriticalSection(&m_CriticalSection);
printf("ServerIO\r\n");
SYSTEM_INFO systemInfo;
HANDLE ioCompletionPort;
HANDLE ioCompletionSocket;
HANDLE *threadHandle;
WSADATA wsData;
SOCKET sService, sClient;
SOCKADDR_IN serviceAddIn, clientAddIn;
DWORD threadId;
int clientAddInLen = sizeof(SOCKADDR_IN);

if (WSAStartup(MAKEWORD(2,2), &wsData) != 0)
{
return -1;
}

ioCompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);

if (ioCompletionPort == NULL)
{
return -1;
}

sService = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

if (sService == INVALID_SOCKET)
{
WSACleanup();
return -1;
}

serviceAddIn.sin_port = htons(PORT);
serviceAddIn.sin_family = AF_INET;
serviceAddIn.sin_addr.S_un.S_addr = htonl(INADDR_ANY);

int iRet = bind(sService, (sockaddr *)&serviceAddIn, sizeof(serviceAddIn));

if (iRet == SOCKET_ERROR)
{
closesocket(sService);
WSACleanup();

return -1;
}

if (listen(sService, BACKLOG) == SOCKET_ERROR)
{
closesocket(sService);
WSACleanup();

return -1;
}

GetSystemInfo(&systemInfo);

threadHandle = new HANDLE[systemInfo.dwNumberOfProcessors * 2];

for (int iCount = 0; iCount < systemInfo.dwNumberOfProcessors * 2; iCount++)
{
threadHandle[iCount] = CreateThread(NULL, 0, ServerThread, ioCompletionPort, 0, &threadId);

if (threadHandle[iCount] == NULL)
{
CloseHandle(threadHandle[iCount]);

return -1;
}
}

while (TRUE)
{
sClient = accept(sService, (struct sockaddr *)&clientAddIn, &clientAddInLen);

if (sClient == INVALID_SOCKET)
{
continue;
}

LP_SOCKET_INFO_DATA lpSocketInfo = new SOCKET_INFO_DATA();

lpSocketInfo->sClient = sClient;
lpSocketInfo->sClientAdd = clientAddIn;
lpSocketInfo->id = sClient;

ioCompletionSocket = CreateIoCompletionPort((HANDLE)sClient, ioCompletionPort, (DWORD)lpSocketInfo, 0);

if (ioCompletionSocket == NULL)
{
closesocket(sClient);
delete lpSocketInfo;
continue;
}

LP_IO_OPERATION_DATA lpOperationData = new IO_OPERATION_DATA();

lpOperationData->wsaBuffer.len = BUFFERLEN;
lpOperationData->wsaBuffer.buf = new char[BUFFERLEN];

EnterCriticalSection(&m_CriticalSection);

socketCount.insert(map<DWORD, LONGLONG>::value_type((DWORD)lpSocketInfo, 1));

LeaveCriticalSection(&m_CriticalSection);

WSARecv(sClient, 
&lpOperationData->wsaBuffer, 
1, 
&lpOperationData->recNumber, 
&lpOperationData->flags, 
&lpOperationData->overLap,
NULL);
}

CloseResource(systemInfo, ioCompletionPort, sService, threadHandle);

return 0;
}


--------------------编程问答-------------------- client
[#include "stdafx.h"
#include <winsock2.h>
#define PORT 4999
#define BACKLOG 100
#define BUFFERLEN 30
#define CLOSE_SERVICE_NUM 0xFFFFFFFF

#pragma comment(lib, "ws2_32.lib")

int _tmain(int argc, _TCHAR* argv[])
{
printf("Center");

SYSTEM_INFO systemInfo;
HANDLE ioCompletionPort;
HANDLE ioCompletionSocket;
HANDLE *threadHandle;
WSADATA wsData;
SOCKET sService, sClient;
SOCKADDR_IN serviceAddIn, clientAddIn;
DWORD threadId;
int clientAddInLen = sizeof(SOCKADDR_IN);

if (WSAStartup(MAKEWORD(2,2), &wsData) != 0)
{
return -1;
}
//sService = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

//if (sService == INVALID_SOCKET)
//{
// WSACleanup();
// return -1;
//}

//serviceAddIn.sin_port = htons(PORT);
//serviceAddIn.sin_family = AF_INET;
//serviceAddIn.sin_addr.s_addr = inet_addr("192.160.10.125");

//int iRet = connect(sService, (sockaddr *)&serviceAddIn, sizeof(serviceAddIn));

//if (iRet == SOCKET_ERROR)
//{
// closesocket(sService);
// WSACleanup();

// return -1;
//}
char *buf;

bool re = FALSE;

int i = 0;
while (TRUE)
{
if (i == 1)
{
//closesocket(sService);
//break;
continue;
}

sService = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

if (sService == INVALID_SOCKET)
{
//WSACleanup();
continue;
}

serviceAddIn.sin_port = htons(PORT);
serviceAddIn.sin_family = AF_INET;
serviceAddIn.sin_addr.s_addr = inet_addr("192.160.10.125");

int iRet = connect(sService, (sockaddr *)&serviceAddIn, sizeof(serviceAddIn));

if (iRet == SOCKET_ERROR)
{
printf("SOCKETID:%d\r\n", sService);
printf("Error:%d\r\n", GetLastError());
/*closesocket(sService);
WSACleanup();*/

continue;
}

char *pxx ;//= "AAAAAAAAAAAAAAAA";
pxx = (char *) malloc(30);
memset(pxx, 'A', 30);

for (int k = 0; k<20; k++)
{
(*(pxx+k))++;
}

buf = (char *) malloc(20);
memcpy(buf, pxx, 20);

if( send( sService, (char *)buf, 30, 0 ) == -1 )
{
int i =0;
}

//i++;

    closesocket(sService);
}

char s;

scanf("%c", &s);

return 0;
}
--------------------编程问答-------------------- 我大体看了一下,threadHandle没有释放,在最后加上:
CloseResource(systemInfo, ioCompletionPort, sService, threadHandle);
if (threadHandle)
{
delete threadHandle;
threadHandle = NULL;
}

return 0;
} --------------------编程问答-------------------- 谢谢。我已经排查了一天了。不过实在看不出来。。。。。。所以请大家指出我写错的地方。。。
HEAP[SocketCompletionIO.exe]: HEAP: Free Heap block e56648 modified at e56690 after it was freed
这个是崩掉的原因。。。不过我不明白为什么会用到释放的指针。。。。。。 --------------------编程问答-------------------- 恩。谢谢。不过运行中一直在while中不断的接受client端的连接。。。。所以还没有走到后面。。。。
是在接受的处理中报错的。。。。所以一直怀疑是IOCP写错了。。。 --------------------编程问答-------------------- 额。。。我运行了一下,不管怎么操作都没有内存泄露。你说一下你的操作步骤 --------------------编程问答-------------------- 应该不是thread的handle没有释放的原因 --------------------编程问答-------------------- 是这样的。。我的client端模拟的情形是迅速连接迅速释放的情况。。。。我开了5个client端的exe去连接server端。。。server是在debug的模式下运行的。。。运行了不久。server就报错了。
EAP[SocketCompletionIO.exe]: HEAP: Free Heap block e56648 modified at e56690 after it was freed 
通常都是这样一句话。。。。。。当然在release下我也试过了。。。。。运行的久一点也会报错的:( --------------------编程问答-------------------- 补充说明一点每个client端都有个死循环在不断创建connect和关闭connect。。。。 --------------------编程问答-------------------- new / delete
new[] / delete[]

本着这样的原则,永远就不会有内漏. --------------------编程问答-------------------- 我source已经送上了。大家调试结果怎么样啊。。。而且有个很奇怪的现象在main线程会报错。中断显示是在iterator 的析构函数中。。
__CLR_OR_THIS_CALL ~_Iterator_base()
{ // destroy the iterator
_Lockit _Lock(_LOCK_DEBUG);
_Orphan_me();
}
请教大家。。map<DWORD, LONGLONG>::iterator 可以用在多线程中吗 --------------------编程问答-------------------- stl不是线程安全的,就是需要你自己做保护。
--------------------编程问答-------------------- 不是thread的handle没有释放的原因 --------------------编程问答-------------------- stl不是线程安全的,就是需要你自己做保护。 --------------------编程问答-------------------- 出错的时候看不到调用栈吗? --------------------编程问答-------------------- 这么长阿!!
那啥, 不知道可不可以这样,你找到你的pdb文件,用windbg分析一下,应该就找到原因了
补充:.NET技术 ,  VC.NET
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,