36 个解决方案
#1
#define PORT 8007
#define DATA_BUFSIZE 1024
#pragma comment(lib, "Ws2_32")
typedef struct
{
OVERLAPPED Overlapped;
WSABUF DataBuf;
CHAR Buffer[DATA_BUFSIZE];
DWORD BytesSEND;
DWORD BytesRECV;
} PER_IO_OPERATION_DATA, * LPPER_IO_OPERATION_DATA;
typedef struct
{
SOCKET Socket;
} PER_HANDLE_DATA, * LPPER_HANDLE_DATA;
DWORD WINAPI ServerWorkerThread(LPVOID CompletionPortID);
/////////////////////////////////////////////////////////////////////////////
// The one and only application object
CWinApp theApp;
using namespace std;
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
int nRetCode = 0;
// initialize MFC and print and error on failure
if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
{
// TODO: change error code to suit your needs
cerr << _T("Fatal Error: MFC initialization failed") << endl;
nRetCode = 1;
}
else
{
// TODO: code your application's behavior here.
CString strHello;
strHello.LoadString(IDS_HELLO);
cout << (LPCTSTR)strHello << endl;
}
count = 0;
SOCKADDR_IN InternetAddr;
SOCKET Listen;
SOCKET Accept;
HANDLE CompletionPort;
SYSTEM_INFO SystemInfo;
LPPER_HANDLE_DATA PerHandleData;
LPPER_IO_OPERATION_DATA PerIoData;
int i;
DWORD RecvBytes;
DWORD Flags;
DWORD ThreadID;
WSADATA wsaData;
DWORD Ret;
sockaddr_in from;
int fromlen=sizeof(from);
if ((Ret = WSAStartup(0x0202, &wsaData)) != 0)
{
printf("WSAStartup failed with error %d\n", Ret);
return 1;
}
// Setup an I/O completion port.
if ((CompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0)) == NULL)
{
printf("CreateIoCompletionPort failed with error: %d\n", GetLastError());
return 1;
}
// Determine how many processors are on the system.
GetSystemInfo(&SystemInfo);
// Create worker threads based on the number of processors available on the
// system. Create two worker threads for each processor.
for(i = 0; i < SystemInfo.dwNumberOfProcessors * 2; i++)
{
HANDLE ThreadHandle;
// Create a server worker thread and pass the completion port to the thread.
if ((ThreadHandle = CreateThread(NULL, 0, ServerWorkerThread, CompletionPort,
0, &ThreadID)) == NULL)
{
printf("CreateThread() failed with error %d\n", GetLastError());
return 1;
}
// Close the thread handle
CloseHandle(ThreadHandle);
}
// Create a listening socket
if ((Listen = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0,
WSA_FLAG_OVERLAPPED)) == INVALID_SOCKET)
{
printf("WSASocket() failed with error %d\n", WSAGetLastError());
return 1;
}
InternetAddr.sin_family = AF_INET;
InternetAddr.sin_addr.s_addr = htonl(INADDR_ANY);
InternetAddr.sin_port = htons(PORT);
if (bind(Listen, (PSOCKADDR) &InternetAddr, sizeof(InternetAddr)) == SOCKET_ERROR)
{
printf("bind() failed with error %d\n", WSAGetLastError());
return 1;
}
// Prepare socket for listening
if (listen(Listen, 5) == SOCKET_ERROR)
{
printf("listen() failed with error %d\n", WSAGetLastError());
return 1;
}
// Accept connections and assign to the completion port.
while(TRUE)
{
if ((Accept = WSAAccept(Listen, (struct sockaddr*)&from,&fromlen, NULL, 0)) == SOCKET_ERROR)
{
printf("WSAAccept() failed with error %d\n", WSAGetLastError());
return 1;
}
// Create a socket information structure to associate with the socket
if ((PerHandleData = (LPPER_HANDLE_DATA) GlobalAlloc(GPTR,
sizeof(PER_HANDLE_DATA))) == NULL)
{
printf("GlobalAlloc() failed with error %d\n", GetLastError());
return 1;
}
// Associate the accepted socket with the original completion port.
cout << "Connection from " << inet_ntoa(from.sin_addr) <<"\r\n";
printf("Socket number %d connected\n", Accept);
PerHandleData->Socket = Accept;
if (CreateIoCompletionPort((HANDLE) Accept, CompletionPort, (DWORD) PerHandleData,
0) == NULL)
{
printf("CreateIoCompletionPort failed with error %d\n", GetLastError());
return 1;
}
// Create per I/O socket information structure to associate with the
// WSARecv call below.
if ((PerIoData = (LPPER_IO_OPERATION_DATA) GlobalAlloc(GPTR,sizeof(PER_IO_OPERATION_DATA))) == NULL)
{
printf("GlobalAlloc() failed with error %d\n", GetLastError());
return 1;
}
ZeroMemory(&(PerIoData->Overlapped), sizeof(OVERLAPPED));
PerIoData->BytesSEND = 0;
PerIoData->BytesRECV = 0;
PerIoData->DataBuf.len = DATA_BUFSIZE;
PerIoData->DataBuf.buf = PerIoData->Buffer;
Flags = 0;
if (WSARecv(Accept, &(PerIoData->DataBuf), 1, &RecvBytes, &Flags,
&(PerIoData->Overlapped), NULL) == SOCKET_ERROR)
{
if (WSAGetLastError() != ERROR_IO_PENDING)
{
printf("WSARecv() failed with error %d\n", WSAGetLastError());
return 1;
}
}
}
return nRetCode;
}
#define DATA_BUFSIZE 1024
#pragma comment(lib, "Ws2_32")
typedef struct
{
OVERLAPPED Overlapped;
WSABUF DataBuf;
CHAR Buffer[DATA_BUFSIZE];
DWORD BytesSEND;
DWORD BytesRECV;
} PER_IO_OPERATION_DATA, * LPPER_IO_OPERATION_DATA;
typedef struct
{
SOCKET Socket;
} PER_HANDLE_DATA, * LPPER_HANDLE_DATA;
DWORD WINAPI ServerWorkerThread(LPVOID CompletionPortID);
/////////////////////////////////////////////////////////////////////////////
// The one and only application object
CWinApp theApp;
using namespace std;
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
int nRetCode = 0;
// initialize MFC and print and error on failure
if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
{
// TODO: change error code to suit your needs
cerr << _T("Fatal Error: MFC initialization failed") << endl;
nRetCode = 1;
}
else
{
// TODO: code your application's behavior here.
CString strHello;
strHello.LoadString(IDS_HELLO);
cout << (LPCTSTR)strHello << endl;
}
count = 0;
SOCKADDR_IN InternetAddr;
SOCKET Listen;
SOCKET Accept;
HANDLE CompletionPort;
SYSTEM_INFO SystemInfo;
LPPER_HANDLE_DATA PerHandleData;
LPPER_IO_OPERATION_DATA PerIoData;
int i;
DWORD RecvBytes;
DWORD Flags;
DWORD ThreadID;
WSADATA wsaData;
DWORD Ret;
sockaddr_in from;
int fromlen=sizeof(from);
if ((Ret = WSAStartup(0x0202, &wsaData)) != 0)
{
printf("WSAStartup failed with error %d\n", Ret);
return 1;
}
// Setup an I/O completion port.
if ((CompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0)) == NULL)
{
printf("CreateIoCompletionPort failed with error: %d\n", GetLastError());
return 1;
}
// Determine how many processors are on the system.
GetSystemInfo(&SystemInfo);
// Create worker threads based on the number of processors available on the
// system. Create two worker threads for each processor.
for(i = 0; i < SystemInfo.dwNumberOfProcessors * 2; i++)
{
HANDLE ThreadHandle;
// Create a server worker thread and pass the completion port to the thread.
if ((ThreadHandle = CreateThread(NULL, 0, ServerWorkerThread, CompletionPort,
0, &ThreadID)) == NULL)
{
printf("CreateThread() failed with error %d\n", GetLastError());
return 1;
}
// Close the thread handle
CloseHandle(ThreadHandle);
}
// Create a listening socket
if ((Listen = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0,
WSA_FLAG_OVERLAPPED)) == INVALID_SOCKET)
{
printf("WSASocket() failed with error %d\n", WSAGetLastError());
return 1;
}
InternetAddr.sin_family = AF_INET;
InternetAddr.sin_addr.s_addr = htonl(INADDR_ANY);
InternetAddr.sin_port = htons(PORT);
if (bind(Listen, (PSOCKADDR) &InternetAddr, sizeof(InternetAddr)) == SOCKET_ERROR)
{
printf("bind() failed with error %d\n", WSAGetLastError());
return 1;
}
// Prepare socket for listening
if (listen(Listen, 5) == SOCKET_ERROR)
{
printf("listen() failed with error %d\n", WSAGetLastError());
return 1;
}
// Accept connections and assign to the completion port.
while(TRUE)
{
if ((Accept = WSAAccept(Listen, (struct sockaddr*)&from,&fromlen, NULL, 0)) == SOCKET_ERROR)
{
printf("WSAAccept() failed with error %d\n", WSAGetLastError());
return 1;
}
// Create a socket information structure to associate with the socket
if ((PerHandleData = (LPPER_HANDLE_DATA) GlobalAlloc(GPTR,
sizeof(PER_HANDLE_DATA))) == NULL)
{
printf("GlobalAlloc() failed with error %d\n", GetLastError());
return 1;
}
// Associate the accepted socket with the original completion port.
cout << "Connection from " << inet_ntoa(from.sin_addr) <<"\r\n";
printf("Socket number %d connected\n", Accept);
PerHandleData->Socket = Accept;
if (CreateIoCompletionPort((HANDLE) Accept, CompletionPort, (DWORD) PerHandleData,
0) == NULL)
{
printf("CreateIoCompletionPort failed with error %d\n", GetLastError());
return 1;
}
// Create per I/O socket information structure to associate with the
// WSARecv call below.
if ((PerIoData = (LPPER_IO_OPERATION_DATA) GlobalAlloc(GPTR,sizeof(PER_IO_OPERATION_DATA))) == NULL)
{
printf("GlobalAlloc() failed with error %d\n", GetLastError());
return 1;
}
ZeroMemory(&(PerIoData->Overlapped), sizeof(OVERLAPPED));
PerIoData->BytesSEND = 0;
PerIoData->BytesRECV = 0;
PerIoData->DataBuf.len = DATA_BUFSIZE;
PerIoData->DataBuf.buf = PerIoData->Buffer;
Flags = 0;
if (WSARecv(Accept, &(PerIoData->DataBuf), 1, &RecvBytes, &Flags,
&(PerIoData->Overlapped), NULL) == SOCKET_ERROR)
{
if (WSAGetLastError() != ERROR_IO_PENDING)
{
printf("WSARecv() failed with error %d\n", WSAGetLastError());
return 1;
}
}
}
return nRetCode;
}
#2
DWORD WINAPI ServerWorkerThread(LPVOID CompletionPortID)
{
HANDLE CompletionPort = (HANDLE) CompletionPortID;
DWORD BytesTransferred;
// LPOVERLAPPED Overlapped;
LPPER_HANDLE_DATA PerHandleData;
LPPER_IO_OPERATION_DATA PerIoData;
DWORD SendBytes, RecvBytes;
DWORD Flags;
while(TRUE)
{
char *toSendtxt = new char[56];
if (GetQueuedCompletionStatus(CompletionPort, &BytesTransferred,
(LPDWORD)&PerHandleData, (LPOVERLAPPED *) &PerIoData, INFINITE) == 0)
{
printf("GetQueuedCompletionStatus failed with error %d\n", GetLastError());
delete []toSendtxt;
//return 0;
}
// long num = ::GetCurrentThreadId();
// First check to see if an error has occured on the socket and if so
// then close the socket and cleanup the SOCKET_INFORMATION structure
// associated with the socket.
if (BytesTransferred == 0)
{
printf("Closing socket %d\n", PerHandleData->Socket);
if (closesocket(PerHandleData->Socket) == SOCKET_ERROR)
{
printf("closesocket() failed with error %d\n", WSAGetLastError());
//return 0;
}
GlobalFree(PerHandleData);
GlobalFree(PerIoData);
delete []toSendtxt;
continue;
}
// Check to see if the BytesRECV field equals zero. If this is so, then
// this means a WSARecv call just completed so update the BytesRECV field
// with the BytesTransferred value from the completed WSARecv() call.
if (PerIoData->BytesRECV == 0)
{
PerIoData->BytesRECV = BytesTransferred;
// cout<<"the received data is :"<<PerIoData->DataBuf.buf<<endl;
toSendtxt = "aaaaaaaaa";
PerIoData->BytesSEND = 0;
}
else
{
PerIoData->BytesSEND += BytesTransferred;
}
if (PerIoData->BytesSEND == 0 )//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 = toSendtxt;//PerIoData->Buffer + PerIoData->BytesSEND;
PerIoData->DataBuf.len = strlen(toSendtxt);//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());
delete []toSendtxt;
//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 = DATA_BUFSIZE;
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());
delete []toSendtxt;
//return 0;
}
}
}//else
}//while
}
///////////////////////////////
以上是服务器的代码
{
HANDLE CompletionPort = (HANDLE) CompletionPortID;
DWORD BytesTransferred;
// LPOVERLAPPED Overlapped;
LPPER_HANDLE_DATA PerHandleData;
LPPER_IO_OPERATION_DATA PerIoData;
DWORD SendBytes, RecvBytes;
DWORD Flags;
while(TRUE)
{
char *toSendtxt = new char[56];
if (GetQueuedCompletionStatus(CompletionPort, &BytesTransferred,
(LPDWORD)&PerHandleData, (LPOVERLAPPED *) &PerIoData, INFINITE) == 0)
{
printf("GetQueuedCompletionStatus failed with error %d\n", GetLastError());
delete []toSendtxt;
//return 0;
}
// long num = ::GetCurrentThreadId();
// First check to see if an error has occured on the socket and if so
// then close the socket and cleanup the SOCKET_INFORMATION structure
// associated with the socket.
if (BytesTransferred == 0)
{
printf("Closing socket %d\n", PerHandleData->Socket);
if (closesocket(PerHandleData->Socket) == SOCKET_ERROR)
{
printf("closesocket() failed with error %d\n", WSAGetLastError());
//return 0;
}
GlobalFree(PerHandleData);
GlobalFree(PerIoData);
delete []toSendtxt;
continue;
}
// Check to see if the BytesRECV field equals zero. If this is so, then
// this means a WSARecv call just completed so update the BytesRECV field
// with the BytesTransferred value from the completed WSARecv() call.
if (PerIoData->BytesRECV == 0)
{
PerIoData->BytesRECV = BytesTransferred;
// cout<<"the received data is :"<<PerIoData->DataBuf.buf<<endl;
toSendtxt = "aaaaaaaaa";
PerIoData->BytesSEND = 0;
}
else
{
PerIoData->BytesSEND += BytesTransferred;
}
if (PerIoData->BytesSEND == 0 )//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 = toSendtxt;//PerIoData->Buffer + PerIoData->BytesSEND;
PerIoData->DataBuf.len = strlen(toSendtxt);//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());
delete []toSendtxt;
//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 = DATA_BUFSIZE;
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());
delete []toSendtxt;
//return 0;
}
}
}//else
}//while
}
///////////////////////////////
以上是服务器的代码
#3
下面贴出客户端的代码:
#include "stdafx.h"
#include "afxsock.h"
#include "conio.h"
#include <process.h>
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
int sock();
int logNum = 0;
#define PORT (u_short) 8007
#define DEST_IP_ADDR "192.168.1.101" //Server address
#define NO_FLAGS_SET 0
/////////////////////////////////////////////////////////////////////////////
// The one and only application object
CWinApp theApp;
using namespace std;
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
int nRetCode = 0;
// initialize MFC and print and error on failure
if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
{
// TODO: change error code to suit your needs
cerr << _T("Fatal Error: MFC initialization failed") << endl;
nRetCode = 1;
}
else
{
// TODO: code your application's behavior here.
CString strHello;
strHello.LoadString(IDS_HELLO);
cout << (LPCTSTR)strHello << endl;
HANDLE hThread;
UINT dwThreadID;
for(int i = 0; i < 1; i++)
{
hThread =(HANDLE) _beginthreadex(NULL,0,ClientThread,0,0,&dwThreadID);
}
CloseHandle(hThread);
while(_getch()!=27);
}
return nRetCode;
}
#include "stdafx.h"
#include "afxsock.h"
#include "conio.h"
#include <process.h>
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
int sock();
int logNum = 0;
#define PORT (u_short) 8007
#define DEST_IP_ADDR "192.168.1.101" //Server address
#define NO_FLAGS_SET 0
/////////////////////////////////////////////////////////////////////////////
// The one and only application object
CWinApp theApp;
using namespace std;
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
int nRetCode = 0;
// initialize MFC and print and error on failure
if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
{
// TODO: change error code to suit your needs
cerr << _T("Fatal Error: MFC initialization failed") << endl;
nRetCode = 1;
}
else
{
// TODO: code your application's behavior here.
CString strHello;
strHello.LoadString(IDS_HELLO);
cout << (LPCTSTR)strHello << endl;
HANDLE hThread;
UINT dwThreadID;
for(int i = 0; i < 1; i++)
{
hThread =(HANDLE) _beginthreadex(NULL,0,ClientThread,0,0,&dwThreadID);
}
CloseHandle(hThread);
while(_getch()!=27);
}
return nRetCode;
}
#4
可能是内存碎片(代码太长,没时间看 ^_^),把每次分配的内存固定为分页大小(GetSystemInfo可以取得,通常为4k).
#5
僵尸哥讲的我也考虑过,现在我把内存分配为1k的整数倍,不知道这样会不会也有问题。不过我还是会试试4k的,谢谢先!
#6
兄弟 搞定了 不要忘记给我说说啊 谢谢 愁思我了
#7
他不可能搞定
因为根本不是那么回事
因为根本不是那么回事
#8
char *toSendtxt = new char[56];
......
toSendtxt = "aaaaaaaaa"; //<--修改为strcpy(toSendtxt , "aaaaaaaaa"); 否则toSendtxt指针指向改变当然不能正确释放了
......
toSendtxt = "aaaaaaaaa"; //<--修改为strcpy(toSendtxt , "aaaaaaaaa"); 否则toSendtxt指针指向改变当然不能正确释放了
#9
strcpy(toSendtxt , "aaaaaaaaa");我也试过的,还是没有用。不过我发现在xp下涨的很少,2003下却涨得很快,真是奇怪啊!不知道liqiang123abc有什么好的建议啊?
#10
你那个是缓存页面的问题
我以前也遇到过
很难解决
我以前也遇到过
很难解决
#11
不会吧,如果真是那样,那就惨了!还想请教一个问题:
typedef struct
{
SOCKET Socket;
} PER_HANDLE_DATA, * LPPER_HANDLE_DATA;
上面的结构体中加入一个类的指针,比如:
typedef struct
{
SOCKET Socket;
CMyClass * myclass;
} PER_HANDLE_DATA, * LPPER_HANDLE_DATA;
在debug运行,VC自己会报内存泄露,我是想让每个socket对应每个类的,这是怎么回事呢?
请高手指点!
#12
还真如liqiang123abc所说的,这个问题搞不定了!
郁闷的是同样是2003系统,一个没有问题,另一个确有问题,唉!!!
#13
这个非得对缓存页面的原理十分熟悉,
才能搞定呢
我不信你能搞定,
我的那个就没搞定,
最后不了了之。。。
才能搞定呢
我不信你能搞定,
我的那个就没搞定,
最后不了了之。。。
#14
首先,WSASend/WSARecv调用失败需要判断是否为IO_Pending,如果不是则需要对内存进行释放;
其次,GetQueuedCompletionStatus返回为False也需要根据情况对内存进行释放,因为这当中可能是另外一个线程提交的WSASend/WSARecv,但是由于还在操作过程当中,该线程意外退出,可能会导致GetQueuedCompletionStatus返回,此时返回值为False,但是交不意味着当中的其它参数无效;
再一个,就是楼主对于Send/Recv的处理代码不明确,虽然在这个echo测试当中无关紧要,但是写这个测试不就是为了以后的成熟应用吗?所以一切都要以一个应用来考虑。
其次,GetQueuedCompletionStatus返回为False也需要根据情况对内存进行释放,因为这当中可能是另外一个线程提交的WSASend/WSARecv,但是由于还在操作过程当中,该线程意外退出,可能会导致GetQueuedCompletionStatus返回,此时返回值为False,但是交不意味着当中的其它参数无效;
再一个,就是楼主对于Send/Recv的处理代码不明确,虽然在这个echo测试当中无关紧要,但是写这个测试不就是为了以后的成熟应用吗?所以一切都要以一个应用来考虑。
#15
不过那个struct当中包含指针的问题,应该是属于程序当中的处理问题,比如说,你的对象是在堆栈上创建的,虽然你保存了指针,但是对象在函数执行完之后就已经释放掉了,而你再去操作实指针,根本就得不到实例。
#16
对于这个问题,我已经不报希望了,多谢大家的积极讨论!!
#17
你刚学网络编程是不可能解决这个问题滴
等你以后经验多了
就能解决了
等你以后经验多了
就能解决了
#18
两处错误:
1、toSendtxt = "aaaaaaaaa"; 改变了指针,使即将运行的delete语句无效。
2、每次循环都 char *toSendtxt = new char[56]; 但是不是每次循环都会delete的,有时delete语句没有机会执行。
1、toSendtxt = "aaaaaaaaa"; 改变了指针,使即将运行的delete语句无效。
2、每次循环都 char *toSendtxt = new char[56]; 但是不是每次循环都会delete的,有时delete语句没有机会执行。
#19
回复人:awu999328() ( 一级(初级)) 信誉:100 2007-7-30 11:07:28 得分:0
对于这个问题,我已经不报希望了,多谢大家的积极讨论!!
-----------------------
肯定是你分配了内存没有释放啊,怎么扯到 什么 "缓存页面"去了.
仔细检查和每个client关联的那个结构体.是否在断开连接的时候释放了内存.
对于这个问题,我已经不报希望了,多谢大家的积极讨论!!
-----------------------
肯定是你分配了内存没有释放啊,怎么扯到 什么 "缓存页面"去了.
仔细检查和每个client关联的那个结构体.是否在断开连接的时候释放了内存.
#20
不建议你在循环中创建、删除,这一定会造成内存碎片。(在循环外创建然后再循环内使用不好?)
可能高手们看的问题较深,能仔细讲解缓存页面的问题。
我看到过高手写的文章关于提高完成端口性能的。
1、使用AcceptEx代替Accept
2、程序启动的时候创建一定数量的socket结构,这样就不会频繁创建于释放造成内存碎片的产生,当超过这个数量才创建与释放
#21
说个好方法,创建一个BUFFER数组,为每个线程创建一个BUFFER,然后直接取就可以用了,不需要每次都new的
#22
在分配和释放内存的地方都加上调试信息,显示指针地址。
统计下看看,是不是每个对应的都释放了。
统计下看看,是不是每个对应的都释放了。
#23
其实这个问题你根本没找到具体原因
#24
肯定是哪里内存没释放。
你对这问题不报希望, 那你写这些都是垃圾,而且浪费认真去看你代码的人 的宝贵时间
你对这问题不报希望, 那你写这些都是垃圾,而且浪费认真去看你代码的人 的宝贵时间
#25
总有地方有问题的
#26
char *toSendtxt = new char[56];
......
toSendtxt = "aaaaaaaaa"; //<--修改为strcpy(toSendtxt , "aaaaaaaaa"); 否则toSendtxt指针指向改变当然不能正确释放了
-----
正解 多几个句柄 就当掉了
#27
toSendtxt = "aaaaaaaaa";
你的toSendTxt不是NEW出来的内存么
这样一改
那块内存肯定回收不了了
你把代码改一改
去掉所有的new和delete
直接再循环外边写chan toSendtxt[50]不就得了
你的toSendTxt不是NEW出来的内存么
这样一改
那块内存肯定回收不了了
你把代码改一改
去掉所有的new和delete
直接再循环外边写chan toSendtxt[50]不就得了
#28
用 boundchecker 查一下是哪里泄露不就完了么
#29
想不到还有这么多大哥关心此问题,小弟真是很激动.
其实我不是在每次循环new那个toSendtxt,我改成下面的:
typedef struct
{
SOCKET Socket;
char toSendtxt[56];
} PER_HANDLE_DATA, * LPPER_HANDLE_DATA;
这样GlobalFree就会释放掉
不过这样还是有问题,自己机器跑了6天没有挂掉,而电信机房服务器不到几小时就挂了
虽然我的系统是盗版的2003 企业版
真不知如何是好啊!!!???
#30
跟盗版应该无关,模拟一下电信的环境,多测试一下。
#31
是否有考虑到可能多核及超线程的情况导致问题出现?
#32
呵呵
对你的遭遇表示同情。
但是我无能为力。。。
也遇到类似的情况。
最后还是无可奈何。
只好作罢。。。
对你的遭遇表示同情。
但是我无能为力。。。
也遇到类似的情况。
最后还是无可奈何。
只好作罢。。。
#33
顶. 我等着看答案.
#34
"这样连接了几十万个后"
同时保持连接有几十万个?
同时保持连接有几十万个?
#35
留个记号,慢慢看。关注。
#36
建议兄弟去看看我上传的资料里面有个完成端口实现的聊天室,可以支持15000人同时在线,采用内存池,内存占用很平稳.
#1
#define PORT 8007
#define DATA_BUFSIZE 1024
#pragma comment(lib, "Ws2_32")
typedef struct
{
OVERLAPPED Overlapped;
WSABUF DataBuf;
CHAR Buffer[DATA_BUFSIZE];
DWORD BytesSEND;
DWORD BytesRECV;
} PER_IO_OPERATION_DATA, * LPPER_IO_OPERATION_DATA;
typedef struct
{
SOCKET Socket;
} PER_HANDLE_DATA, * LPPER_HANDLE_DATA;
DWORD WINAPI ServerWorkerThread(LPVOID CompletionPortID);
/////////////////////////////////////////////////////////////////////////////
// The one and only application object
CWinApp theApp;
using namespace std;
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
int nRetCode = 0;
// initialize MFC and print and error on failure
if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
{
// TODO: change error code to suit your needs
cerr << _T("Fatal Error: MFC initialization failed") << endl;
nRetCode = 1;
}
else
{
// TODO: code your application's behavior here.
CString strHello;
strHello.LoadString(IDS_HELLO);
cout << (LPCTSTR)strHello << endl;
}
count = 0;
SOCKADDR_IN InternetAddr;
SOCKET Listen;
SOCKET Accept;
HANDLE CompletionPort;
SYSTEM_INFO SystemInfo;
LPPER_HANDLE_DATA PerHandleData;
LPPER_IO_OPERATION_DATA PerIoData;
int i;
DWORD RecvBytes;
DWORD Flags;
DWORD ThreadID;
WSADATA wsaData;
DWORD Ret;
sockaddr_in from;
int fromlen=sizeof(from);
if ((Ret = WSAStartup(0x0202, &wsaData)) != 0)
{
printf("WSAStartup failed with error %d\n", Ret);
return 1;
}
// Setup an I/O completion port.
if ((CompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0)) == NULL)
{
printf("CreateIoCompletionPort failed with error: %d\n", GetLastError());
return 1;
}
// Determine how many processors are on the system.
GetSystemInfo(&SystemInfo);
// Create worker threads based on the number of processors available on the
// system. Create two worker threads for each processor.
for(i = 0; i < SystemInfo.dwNumberOfProcessors * 2; i++)
{
HANDLE ThreadHandle;
// Create a server worker thread and pass the completion port to the thread.
if ((ThreadHandle = CreateThread(NULL, 0, ServerWorkerThread, CompletionPort,
0, &ThreadID)) == NULL)
{
printf("CreateThread() failed with error %d\n", GetLastError());
return 1;
}
// Close the thread handle
CloseHandle(ThreadHandle);
}
// Create a listening socket
if ((Listen = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0,
WSA_FLAG_OVERLAPPED)) == INVALID_SOCKET)
{
printf("WSASocket() failed with error %d\n", WSAGetLastError());
return 1;
}
InternetAddr.sin_family = AF_INET;
InternetAddr.sin_addr.s_addr = htonl(INADDR_ANY);
InternetAddr.sin_port = htons(PORT);
if (bind(Listen, (PSOCKADDR) &InternetAddr, sizeof(InternetAddr)) == SOCKET_ERROR)
{
printf("bind() failed with error %d\n", WSAGetLastError());
return 1;
}
// Prepare socket for listening
if (listen(Listen, 5) == SOCKET_ERROR)
{
printf("listen() failed with error %d\n", WSAGetLastError());
return 1;
}
// Accept connections and assign to the completion port.
while(TRUE)
{
if ((Accept = WSAAccept(Listen, (struct sockaddr*)&from,&fromlen, NULL, 0)) == SOCKET_ERROR)
{
printf("WSAAccept() failed with error %d\n", WSAGetLastError());
return 1;
}
// Create a socket information structure to associate with the socket
if ((PerHandleData = (LPPER_HANDLE_DATA) GlobalAlloc(GPTR,
sizeof(PER_HANDLE_DATA))) == NULL)
{
printf("GlobalAlloc() failed with error %d\n", GetLastError());
return 1;
}
// Associate the accepted socket with the original completion port.
cout << "Connection from " << inet_ntoa(from.sin_addr) <<"\r\n";
printf("Socket number %d connected\n", Accept);
PerHandleData->Socket = Accept;
if (CreateIoCompletionPort((HANDLE) Accept, CompletionPort, (DWORD) PerHandleData,
0) == NULL)
{
printf("CreateIoCompletionPort failed with error %d\n", GetLastError());
return 1;
}
// Create per I/O socket information structure to associate with the
// WSARecv call below.
if ((PerIoData = (LPPER_IO_OPERATION_DATA) GlobalAlloc(GPTR,sizeof(PER_IO_OPERATION_DATA))) == NULL)
{
printf("GlobalAlloc() failed with error %d\n", GetLastError());
return 1;
}
ZeroMemory(&(PerIoData->Overlapped), sizeof(OVERLAPPED));
PerIoData->BytesSEND = 0;
PerIoData->BytesRECV = 0;
PerIoData->DataBuf.len = DATA_BUFSIZE;
PerIoData->DataBuf.buf = PerIoData->Buffer;
Flags = 0;
if (WSARecv(Accept, &(PerIoData->DataBuf), 1, &RecvBytes, &Flags,
&(PerIoData->Overlapped), NULL) == SOCKET_ERROR)
{
if (WSAGetLastError() != ERROR_IO_PENDING)
{
printf("WSARecv() failed with error %d\n", WSAGetLastError());
return 1;
}
}
}
return nRetCode;
}
#define DATA_BUFSIZE 1024
#pragma comment(lib, "Ws2_32")
typedef struct
{
OVERLAPPED Overlapped;
WSABUF DataBuf;
CHAR Buffer[DATA_BUFSIZE];
DWORD BytesSEND;
DWORD BytesRECV;
} PER_IO_OPERATION_DATA, * LPPER_IO_OPERATION_DATA;
typedef struct
{
SOCKET Socket;
} PER_HANDLE_DATA, * LPPER_HANDLE_DATA;
DWORD WINAPI ServerWorkerThread(LPVOID CompletionPortID);
/////////////////////////////////////////////////////////////////////////////
// The one and only application object
CWinApp theApp;
using namespace std;
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
int nRetCode = 0;
// initialize MFC and print and error on failure
if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
{
// TODO: change error code to suit your needs
cerr << _T("Fatal Error: MFC initialization failed") << endl;
nRetCode = 1;
}
else
{
// TODO: code your application's behavior here.
CString strHello;
strHello.LoadString(IDS_HELLO);
cout << (LPCTSTR)strHello << endl;
}
count = 0;
SOCKADDR_IN InternetAddr;
SOCKET Listen;
SOCKET Accept;
HANDLE CompletionPort;
SYSTEM_INFO SystemInfo;
LPPER_HANDLE_DATA PerHandleData;
LPPER_IO_OPERATION_DATA PerIoData;
int i;
DWORD RecvBytes;
DWORD Flags;
DWORD ThreadID;
WSADATA wsaData;
DWORD Ret;
sockaddr_in from;
int fromlen=sizeof(from);
if ((Ret = WSAStartup(0x0202, &wsaData)) != 0)
{
printf("WSAStartup failed with error %d\n", Ret);
return 1;
}
// Setup an I/O completion port.
if ((CompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0)) == NULL)
{
printf("CreateIoCompletionPort failed with error: %d\n", GetLastError());
return 1;
}
// Determine how many processors are on the system.
GetSystemInfo(&SystemInfo);
// Create worker threads based on the number of processors available on the
// system. Create two worker threads for each processor.
for(i = 0; i < SystemInfo.dwNumberOfProcessors * 2; i++)
{
HANDLE ThreadHandle;
// Create a server worker thread and pass the completion port to the thread.
if ((ThreadHandle = CreateThread(NULL, 0, ServerWorkerThread, CompletionPort,
0, &ThreadID)) == NULL)
{
printf("CreateThread() failed with error %d\n", GetLastError());
return 1;
}
// Close the thread handle
CloseHandle(ThreadHandle);
}
// Create a listening socket
if ((Listen = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0,
WSA_FLAG_OVERLAPPED)) == INVALID_SOCKET)
{
printf("WSASocket() failed with error %d\n", WSAGetLastError());
return 1;
}
InternetAddr.sin_family = AF_INET;
InternetAddr.sin_addr.s_addr = htonl(INADDR_ANY);
InternetAddr.sin_port = htons(PORT);
if (bind(Listen, (PSOCKADDR) &InternetAddr, sizeof(InternetAddr)) == SOCKET_ERROR)
{
printf("bind() failed with error %d\n", WSAGetLastError());
return 1;
}
// Prepare socket for listening
if (listen(Listen, 5) == SOCKET_ERROR)
{
printf("listen() failed with error %d\n", WSAGetLastError());
return 1;
}
// Accept connections and assign to the completion port.
while(TRUE)
{
if ((Accept = WSAAccept(Listen, (struct sockaddr*)&from,&fromlen, NULL, 0)) == SOCKET_ERROR)
{
printf("WSAAccept() failed with error %d\n", WSAGetLastError());
return 1;
}
// Create a socket information structure to associate with the socket
if ((PerHandleData = (LPPER_HANDLE_DATA) GlobalAlloc(GPTR,
sizeof(PER_HANDLE_DATA))) == NULL)
{
printf("GlobalAlloc() failed with error %d\n", GetLastError());
return 1;
}
// Associate the accepted socket with the original completion port.
cout << "Connection from " << inet_ntoa(from.sin_addr) <<"\r\n";
printf("Socket number %d connected\n", Accept);
PerHandleData->Socket = Accept;
if (CreateIoCompletionPort((HANDLE) Accept, CompletionPort, (DWORD) PerHandleData,
0) == NULL)
{
printf("CreateIoCompletionPort failed with error %d\n", GetLastError());
return 1;
}
// Create per I/O socket information structure to associate with the
// WSARecv call below.
if ((PerIoData = (LPPER_IO_OPERATION_DATA) GlobalAlloc(GPTR,sizeof(PER_IO_OPERATION_DATA))) == NULL)
{
printf("GlobalAlloc() failed with error %d\n", GetLastError());
return 1;
}
ZeroMemory(&(PerIoData->Overlapped), sizeof(OVERLAPPED));
PerIoData->BytesSEND = 0;
PerIoData->BytesRECV = 0;
PerIoData->DataBuf.len = DATA_BUFSIZE;
PerIoData->DataBuf.buf = PerIoData->Buffer;
Flags = 0;
if (WSARecv(Accept, &(PerIoData->DataBuf), 1, &RecvBytes, &Flags,
&(PerIoData->Overlapped), NULL) == SOCKET_ERROR)
{
if (WSAGetLastError() != ERROR_IO_PENDING)
{
printf("WSARecv() failed with error %d\n", WSAGetLastError());
return 1;
}
}
}
return nRetCode;
}
#2
DWORD WINAPI ServerWorkerThread(LPVOID CompletionPortID)
{
HANDLE CompletionPort = (HANDLE) CompletionPortID;
DWORD BytesTransferred;
// LPOVERLAPPED Overlapped;
LPPER_HANDLE_DATA PerHandleData;
LPPER_IO_OPERATION_DATA PerIoData;
DWORD SendBytes, RecvBytes;
DWORD Flags;
while(TRUE)
{
char *toSendtxt = new char[56];
if (GetQueuedCompletionStatus(CompletionPort, &BytesTransferred,
(LPDWORD)&PerHandleData, (LPOVERLAPPED *) &PerIoData, INFINITE) == 0)
{
printf("GetQueuedCompletionStatus failed with error %d\n", GetLastError());
delete []toSendtxt;
//return 0;
}
// long num = ::GetCurrentThreadId();
// First check to see if an error has occured on the socket and if so
// then close the socket and cleanup the SOCKET_INFORMATION structure
// associated with the socket.
if (BytesTransferred == 0)
{
printf("Closing socket %d\n", PerHandleData->Socket);
if (closesocket(PerHandleData->Socket) == SOCKET_ERROR)
{
printf("closesocket() failed with error %d\n", WSAGetLastError());
//return 0;
}
GlobalFree(PerHandleData);
GlobalFree(PerIoData);
delete []toSendtxt;
continue;
}
// Check to see if the BytesRECV field equals zero. If this is so, then
// this means a WSARecv call just completed so update the BytesRECV field
// with the BytesTransferred value from the completed WSARecv() call.
if (PerIoData->BytesRECV == 0)
{
PerIoData->BytesRECV = BytesTransferred;
// cout<<"the received data is :"<<PerIoData->DataBuf.buf<<endl;
toSendtxt = "aaaaaaaaa";
PerIoData->BytesSEND = 0;
}
else
{
PerIoData->BytesSEND += BytesTransferred;
}
if (PerIoData->BytesSEND == 0 )//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 = toSendtxt;//PerIoData->Buffer + PerIoData->BytesSEND;
PerIoData->DataBuf.len = strlen(toSendtxt);//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());
delete []toSendtxt;
//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 = DATA_BUFSIZE;
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());
delete []toSendtxt;
//return 0;
}
}
}//else
}//while
}
///////////////////////////////
以上是服务器的代码
{
HANDLE CompletionPort = (HANDLE) CompletionPortID;
DWORD BytesTransferred;
// LPOVERLAPPED Overlapped;
LPPER_HANDLE_DATA PerHandleData;
LPPER_IO_OPERATION_DATA PerIoData;
DWORD SendBytes, RecvBytes;
DWORD Flags;
while(TRUE)
{
char *toSendtxt = new char[56];
if (GetQueuedCompletionStatus(CompletionPort, &BytesTransferred,
(LPDWORD)&PerHandleData, (LPOVERLAPPED *) &PerIoData, INFINITE) == 0)
{
printf("GetQueuedCompletionStatus failed with error %d\n", GetLastError());
delete []toSendtxt;
//return 0;
}
// long num = ::GetCurrentThreadId();
// First check to see if an error has occured on the socket and if so
// then close the socket and cleanup the SOCKET_INFORMATION structure
// associated with the socket.
if (BytesTransferred == 0)
{
printf("Closing socket %d\n", PerHandleData->Socket);
if (closesocket(PerHandleData->Socket) == SOCKET_ERROR)
{
printf("closesocket() failed with error %d\n", WSAGetLastError());
//return 0;
}
GlobalFree(PerHandleData);
GlobalFree(PerIoData);
delete []toSendtxt;
continue;
}
// Check to see if the BytesRECV field equals zero. If this is so, then
// this means a WSARecv call just completed so update the BytesRECV field
// with the BytesTransferred value from the completed WSARecv() call.
if (PerIoData->BytesRECV == 0)
{
PerIoData->BytesRECV = BytesTransferred;
// cout<<"the received data is :"<<PerIoData->DataBuf.buf<<endl;
toSendtxt = "aaaaaaaaa";
PerIoData->BytesSEND = 0;
}
else
{
PerIoData->BytesSEND += BytesTransferred;
}
if (PerIoData->BytesSEND == 0 )//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 = toSendtxt;//PerIoData->Buffer + PerIoData->BytesSEND;
PerIoData->DataBuf.len = strlen(toSendtxt);//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());
delete []toSendtxt;
//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 = DATA_BUFSIZE;
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());
delete []toSendtxt;
//return 0;
}
}
}//else
}//while
}
///////////////////////////////
以上是服务器的代码
#3
下面贴出客户端的代码:
#include "stdafx.h"
#include "afxsock.h"
#include "conio.h"
#include <process.h>
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
int sock();
int logNum = 0;
#define PORT (u_short) 8007
#define DEST_IP_ADDR "192.168.1.101" //Server address
#define NO_FLAGS_SET 0
/////////////////////////////////////////////////////////////////////////////
// The one and only application object
CWinApp theApp;
using namespace std;
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
int nRetCode = 0;
// initialize MFC and print and error on failure
if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
{
// TODO: change error code to suit your needs
cerr << _T("Fatal Error: MFC initialization failed") << endl;
nRetCode = 1;
}
else
{
// TODO: code your application's behavior here.
CString strHello;
strHello.LoadString(IDS_HELLO);
cout << (LPCTSTR)strHello << endl;
HANDLE hThread;
UINT dwThreadID;
for(int i = 0; i < 1; i++)
{
hThread =(HANDLE) _beginthreadex(NULL,0,ClientThread,0,0,&dwThreadID);
}
CloseHandle(hThread);
while(_getch()!=27);
}
return nRetCode;
}
#include "stdafx.h"
#include "afxsock.h"
#include "conio.h"
#include <process.h>
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
int sock();
int logNum = 0;
#define PORT (u_short) 8007
#define DEST_IP_ADDR "192.168.1.101" //Server address
#define NO_FLAGS_SET 0
/////////////////////////////////////////////////////////////////////////////
// The one and only application object
CWinApp theApp;
using namespace std;
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
int nRetCode = 0;
// initialize MFC and print and error on failure
if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
{
// TODO: change error code to suit your needs
cerr << _T("Fatal Error: MFC initialization failed") << endl;
nRetCode = 1;
}
else
{
// TODO: code your application's behavior here.
CString strHello;
strHello.LoadString(IDS_HELLO);
cout << (LPCTSTR)strHello << endl;
HANDLE hThread;
UINT dwThreadID;
for(int i = 0; i < 1; i++)
{
hThread =(HANDLE) _beginthreadex(NULL,0,ClientThread,0,0,&dwThreadID);
}
CloseHandle(hThread);
while(_getch()!=27);
}
return nRetCode;
}
#4
可能是内存碎片(代码太长,没时间看 ^_^),把每次分配的内存固定为分页大小(GetSystemInfo可以取得,通常为4k).
#5
僵尸哥讲的我也考虑过,现在我把内存分配为1k的整数倍,不知道这样会不会也有问题。不过我还是会试试4k的,谢谢先!
#6
兄弟 搞定了 不要忘记给我说说啊 谢谢 愁思我了
#7
他不可能搞定
因为根本不是那么回事
因为根本不是那么回事
#8
char *toSendtxt = new char[56];
......
toSendtxt = "aaaaaaaaa"; //<--修改为strcpy(toSendtxt , "aaaaaaaaa"); 否则toSendtxt指针指向改变当然不能正确释放了
......
toSendtxt = "aaaaaaaaa"; //<--修改为strcpy(toSendtxt , "aaaaaaaaa"); 否则toSendtxt指针指向改变当然不能正确释放了
#9
strcpy(toSendtxt , "aaaaaaaaa");我也试过的,还是没有用。不过我发现在xp下涨的很少,2003下却涨得很快,真是奇怪啊!不知道liqiang123abc有什么好的建议啊?
#10
你那个是缓存页面的问题
我以前也遇到过
很难解决
我以前也遇到过
很难解决
#11
不会吧,如果真是那样,那就惨了!还想请教一个问题:
typedef struct
{
SOCKET Socket;
} PER_HANDLE_DATA, * LPPER_HANDLE_DATA;
上面的结构体中加入一个类的指针,比如:
typedef struct
{
SOCKET Socket;
CMyClass * myclass;
} PER_HANDLE_DATA, * LPPER_HANDLE_DATA;
在debug运行,VC自己会报内存泄露,我是想让每个socket对应每个类的,这是怎么回事呢?
请高手指点!
#12
还真如liqiang123abc所说的,这个问题搞不定了!
郁闷的是同样是2003系统,一个没有问题,另一个确有问题,唉!!!
#13
这个非得对缓存页面的原理十分熟悉,
才能搞定呢
我不信你能搞定,
我的那个就没搞定,
最后不了了之。。。
才能搞定呢
我不信你能搞定,
我的那个就没搞定,
最后不了了之。。。
#14
首先,WSASend/WSARecv调用失败需要判断是否为IO_Pending,如果不是则需要对内存进行释放;
其次,GetQueuedCompletionStatus返回为False也需要根据情况对内存进行释放,因为这当中可能是另外一个线程提交的WSASend/WSARecv,但是由于还在操作过程当中,该线程意外退出,可能会导致GetQueuedCompletionStatus返回,此时返回值为False,但是交不意味着当中的其它参数无效;
再一个,就是楼主对于Send/Recv的处理代码不明确,虽然在这个echo测试当中无关紧要,但是写这个测试不就是为了以后的成熟应用吗?所以一切都要以一个应用来考虑。
其次,GetQueuedCompletionStatus返回为False也需要根据情况对内存进行释放,因为这当中可能是另外一个线程提交的WSASend/WSARecv,但是由于还在操作过程当中,该线程意外退出,可能会导致GetQueuedCompletionStatus返回,此时返回值为False,但是交不意味着当中的其它参数无效;
再一个,就是楼主对于Send/Recv的处理代码不明确,虽然在这个echo测试当中无关紧要,但是写这个测试不就是为了以后的成熟应用吗?所以一切都要以一个应用来考虑。
#15
不过那个struct当中包含指针的问题,应该是属于程序当中的处理问题,比如说,你的对象是在堆栈上创建的,虽然你保存了指针,但是对象在函数执行完之后就已经释放掉了,而你再去操作实指针,根本就得不到实例。
#16
对于这个问题,我已经不报希望了,多谢大家的积极讨论!!
#17
你刚学网络编程是不可能解决这个问题滴
等你以后经验多了
就能解决了
等你以后经验多了
就能解决了
#18
两处错误:
1、toSendtxt = "aaaaaaaaa"; 改变了指针,使即将运行的delete语句无效。
2、每次循环都 char *toSendtxt = new char[56]; 但是不是每次循环都会delete的,有时delete语句没有机会执行。
1、toSendtxt = "aaaaaaaaa"; 改变了指针,使即将运行的delete语句无效。
2、每次循环都 char *toSendtxt = new char[56]; 但是不是每次循环都会delete的,有时delete语句没有机会执行。
#19
回复人:awu999328() ( 一级(初级)) 信誉:100 2007-7-30 11:07:28 得分:0
对于这个问题,我已经不报希望了,多谢大家的积极讨论!!
-----------------------
肯定是你分配了内存没有释放啊,怎么扯到 什么 "缓存页面"去了.
仔细检查和每个client关联的那个结构体.是否在断开连接的时候释放了内存.
对于这个问题,我已经不报希望了,多谢大家的积极讨论!!
-----------------------
肯定是你分配了内存没有释放啊,怎么扯到 什么 "缓存页面"去了.
仔细检查和每个client关联的那个结构体.是否在断开连接的时候释放了内存.
#20
不建议你在循环中创建、删除,这一定会造成内存碎片。(在循环外创建然后再循环内使用不好?)
可能高手们看的问题较深,能仔细讲解缓存页面的问题。
我看到过高手写的文章关于提高完成端口性能的。
1、使用AcceptEx代替Accept
2、程序启动的时候创建一定数量的socket结构,这样就不会频繁创建于释放造成内存碎片的产生,当超过这个数量才创建与释放
#21
说个好方法,创建一个BUFFER数组,为每个线程创建一个BUFFER,然后直接取就可以用了,不需要每次都new的
#22
在分配和释放内存的地方都加上调试信息,显示指针地址。
统计下看看,是不是每个对应的都释放了。
统计下看看,是不是每个对应的都释放了。
#23
其实这个问题你根本没找到具体原因
#24
肯定是哪里内存没释放。
你对这问题不报希望, 那你写这些都是垃圾,而且浪费认真去看你代码的人 的宝贵时间
你对这问题不报希望, 那你写这些都是垃圾,而且浪费认真去看你代码的人 的宝贵时间
#25
总有地方有问题的
#26
char *toSendtxt = new char[56];
......
toSendtxt = "aaaaaaaaa"; //<--修改为strcpy(toSendtxt , "aaaaaaaaa"); 否则toSendtxt指针指向改变当然不能正确释放了
-----
正解 多几个句柄 就当掉了
#27
toSendtxt = "aaaaaaaaa";
你的toSendTxt不是NEW出来的内存么
这样一改
那块内存肯定回收不了了
你把代码改一改
去掉所有的new和delete
直接再循环外边写chan toSendtxt[50]不就得了
你的toSendTxt不是NEW出来的内存么
这样一改
那块内存肯定回收不了了
你把代码改一改
去掉所有的new和delete
直接再循环外边写chan toSendtxt[50]不就得了
#28
用 boundchecker 查一下是哪里泄露不就完了么
#29
想不到还有这么多大哥关心此问题,小弟真是很激动.
其实我不是在每次循环new那个toSendtxt,我改成下面的:
typedef struct
{
SOCKET Socket;
char toSendtxt[56];
} PER_HANDLE_DATA, * LPPER_HANDLE_DATA;
这样GlobalFree就会释放掉
不过这样还是有问题,自己机器跑了6天没有挂掉,而电信机房服务器不到几小时就挂了
虽然我的系统是盗版的2003 企业版
真不知如何是好啊!!!???
#30
跟盗版应该无关,模拟一下电信的环境,多测试一下。
#31
是否有考虑到可能多核及超线程的情况导致问题出现?
#32
呵呵
对你的遭遇表示同情。
但是我无能为力。。。
也遇到类似的情况。
最后还是无可奈何。
只好作罢。。。
对你的遭遇表示同情。
但是我无能为力。。。
也遇到类似的情况。
最后还是无可奈何。
只好作罢。。。
#33
顶. 我等着看答案.
#34
"这样连接了几十万个后"
同时保持连接有几十万个?
同时保持连接有几十万个?
#35
留个记号,慢慢看。关注。
#36
建议兄弟去看看我上传的资料里面有个完成端口实现的聊天室,可以支持15000人同时在线,采用内存池,内存占用很平稳.