关于SOCKET一个代理服务器内存泄露问题。请高手指教

betterwxf3131 2007-08-09 09:11:36
我写了个基于SOCKET的代理服务器。我的模式是为每一个收到的SOCKET连接创建一个线程。在我的接受函数中。我又会创建一个子线程,为的是接受函数时超时返回,可我发现这样的话我的内存存在泄露。是不是线程函数创建太多了。哪位高手能帮我改改吗。怎么可以不用创建线程序也能实现接受。发送超时。帮小弟出出主意拉。急!谢谢了!欢迎高手讨论
...全文
296 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
gister 2007-08-09
  • 打赏
  • 举报
回复
楼主说得有点不清楚,把代码贴出来看看
zdleek 2007-08-09
  • 打赏
  • 举报
回复
内存泄露可以用bonuscheck检查,如果你自己没有主意的话
不过自己的程序,通常自己仔细查找是可以发现的
僵哥 2007-08-09
  • 打赏
  • 举报
回复
代理服务器如果为自己的每一个连接都创建一个线程甚至更多线程的话,那么这个代理服务器能承载多少个用户?一个进程又能够创建得起来多少个线程,而这些线程又有多少个同时工作的?

对于内存泄露,这个只能靠自己或者工具去查。
easyrock 2007-08-09
  • 打赏
  • 举报
回复
[accept]
--[起新线程]
----[握手]
----[连目标地址]
----[循环]
------[select(客户端点,目标端点)]
------[如果(客户端点)有数据]
--------客户端点->目标端点
------[如果(目标端点)有数据]
--------目标端点->客户端点
easyrock 2007-08-09
  • 打赏
  • 举报
回复
为什么要每个连接要耗费两个线程??最多一个就够了.
[accept]
[起新线程]
[握手]
[连目标地址]
[循环]
[select(客户端点,目标端点)]
[如果(客户端点)有数据]
客户端点->目标端点
[如果(目标端点)有数据]
目标端点->客户端点
betterwxf3131 2007-08-09
  • 打赏
  • 举报
回复
还是感觉很迷茫。我的程序运行几天后会出现10055错误。也就是缓冲区不足
netcreator 2007-08-09
  • 打赏
  • 举报
回复
思路没问题
应该是这样弄
只是建议在accept后返回的新socket你要管理起来(在数量未知情况下通常我用链表管理),在有事件返回时在消息处理函数中处理返回的事件,接收相应的socket接受的数据则建议在消息处理函数中进行,而处理这些数据可由子线程完成,这是用的mfc的异步模式
如果想纯粹地用子线程处理所有事件,则就无法用消息处理机制,可以用select在子线程中去处理相应的socket,包括销毁该socket都可以(系统并不会释放相应的空间)不过,这样释放不干净,好像并没有什么好的办法,因为你也close了,也set null了,系统不释放是系统底层socket的工作机制,伯克利就是这样做的,应该也有它的道理。除非你自己写一个socket来处理,否则你就只能调用这些东东了。好在,一个socket句柄占用的空间并不多,占空间最多的是接受数据后new出的空间,那个记得释放就好了。在底层socket会管理得比较好,最后侦听的母socket记得销毁就好了
Avoid 2007-08-09
  • 打赏
  • 举报
回复
一般来说是lz没有关闭SOCKET造成的。
betterwxf3131 2007-08-09
  • 打赏
  • 举报
回复
我仔细的看下了程序。发现有个地方不是很明白,可能会出现问题
DWORD CALLBACK CWSocket::ServerProc(LPVOID lpParm)
{
SERVERPARA *para = (SERVERPARA*)lpParm;

if(para == NULL) return -1;

SOCKET s = para->s;
int port = para->port;
DEALPROC lpDealFunc = para->lpDealFunc;
delete para;

SOCKET sClient;
int iAddrSize;
struct sockaddr_in addr;
char IP[32];
HANDLE hThread;
DWORD dwThreadId;
DEALPARA *parac;

iAddrSize = sizeof(addr);

while(1)
{
sClient = accept(s, (struct sockaddr *)&addr, &iAddrSize);

if(sClient == SOCKET_ERROR) break;

sprintf(IP, "%d.%d.%d.%d", addr.sin_addr.S_un.S_un_b.s_b1,
addr.sin_addr.S_un.S_un_b.s_b2,
addr.sin_addr.S_un.S_un_b.s_b3,
addr.sin_addr.S_un.S_un_b.s_b4);

parac = new DEALPARA;
memset(parac->IP, 0, sizeof(parac->IP));
parac->s = sClient;
parac->port = port;
parac->lpDealFunc = lpDealFunc;
memcpy(parac->IP, IP, strlen(IP));

//侦听到连接,开一个线程
hThread = CreateThread(NULL, 0, DealProc, (LPVOID)(parac), 0, &dwThreadId);

if(hThread == NULL) delete parac;
}

return 0;
}
在这里有人说sClient会泄漏资源。最好写成sClient = accept(s, (struct sockaddr *)&addr, &iAddrSize);大家怎么看?
在SOCKET中有个这样的函数
CWSocket::operator=(SOCKET s)
{
if(IsSockConnected(s))
{

m_sSocket = s;
m_bConnected = TRUE;
m_bNeedClose = FALSE;
}
}
BOOL CWSocket::IsSockConnected(SOCKET s)
{
int nRet = 0;
struct fd_set Fd_Recv;
struct timeval Time_Recv;
memset(&Fd_Recv, 0, sizeof(struct fd_set));
FD_CLR(s, &Fd_Recv);
FD_SET(s, &Fd_Recv);
Time_Recv.tv_sec = 0;
Time_Recv.tv_usec = 0;
nRet = select(s, &Fd_Recv, NULL, NULL, &Time_Recv);
return (nRet == 0);
}
当parac->s = sClient会触发这个函数。我后来觉得IsSockConnected可调可不调用。就改成了

CWSocket::operator=(SOCKET s)
{


m_sSocket = s;
m_bConnected = TRUE;
m_bNeedClose = FALSE;

}
会不会有影响呢。。。。。。。。2个疑问 。各位高手给个答案吧。

18,357

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 网络编程
c++c语言开发语言 技术论坛(原bbs)
社区管理员
  • 网络编程
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧