我看了看普遍的做法似乎都是由CAsyncSocket派生两个类,一个Listen用来监听客户端连接,另一个Request用来处理客户端请求
void CListenSocket::OnAccept(int nErrorCode)
{
CRequestSocket *pRequest = new CRequestSocket ;
if( !pRequest)
return ;
if ( Accept( *pRequest ) )
{
pRequest->AsyncSelect( FD_READ|FD_CLOSE);
}
CAsyncSocket::OnAccept(nErrorCode);
}
我还是不太了解,这意思是不是说,Listen只负责监听端口,当有新连接的时候,就new一个Request出来,然后怎样响应客户端的请求,就是Request的事情了(比如CRequestSocket::OnReceive里处理客户端发来的东西,等等)如果是这样,那么在CListenSocket::OnAccept中new的Request,当连接断开后,它就是无用的了,如果不释放掉它不就是内存泄露了吗?毕竟MFC没有C#的Garbage Collector特性请各位释疑,如果我的想法不正确,请大家讲讲一般通用的办法,如何用CAsyncSocket做支持多个客户端连接的服务端?
void CListenSocket::OnAccept(int nErrorCode)
{
CRequestSocket *pRequest = new CRequestSocket ;
if( !pRequest)
return ;
if ( Accept( *pRequest ) )
{
pRequest->AsyncSelect( FD_READ|FD_CLOSE);
}
CAsyncSocket::OnAccept(nErrorCode);
}
我还是不太了解,这意思是不是说,Listen只负责监听端口,当有新连接的时候,就new一个Request出来,然后怎样响应客户端的请求,就是Request的事情了(比如CRequestSocket::OnReceive里处理客户端发来的东西,等等)如果是这样,那么在CListenSocket::OnAccept中new的Request,当连接断开后,它就是无用的了,如果不释放掉它不就是内存泄露了吗?毕竟MFC没有C#的Garbage Collector特性请各位释疑,如果我的想法不正确,请大家讲讲一般通用的办法,如何用CAsyncSocket做支持多个客户端连接的服务端?
我的问题是 new出来的东西,断开连接后就不就没用了?那谁来回收它?
一般的方法是怎么做的?
1.
可以将客户端的套接字保存在一个链表中:
CPtrList m_connectionList;
m_connectionList.AddTail(pSocket);//保存该套接字
2.
在OnDestroy()中释放监听套接字和new出来的客户端套接字
if (m_pListeningSocket)
{
delete m_pListeningSocket;
m_pListeningSocket=NULL;
}
//清除链表中所有客户端的套接字
int nSocketNum=m_connectionList.GetCount();
一般ListeningSocket都Destory了,那就是关闭服务端了啊,在服务端都关闭的时候还有必要考虑释放这些吗?
能否做到每个客户端断开连接后,释放为他new的CAsyncSocket?
但是,作为服务器端程序,为避免频繁分配和释放内存造成的性能降低以及内存碎片问题,动态创建的对象应该是基于对象池概念的,该对象所属的类型应该重载new和delete操作符,使之并不是直接分配和释放内存,new的时候先从对象池里取可用对象,如果取不到,再分配内存并把新建的对象放入对象池中,delete的时候将对象池中对应的不用的对象置为可用。
当然,上面说的是按高负荷服务器设计要求来说的,作为普通科研级别的习作可以忽略这个。
因为onclose只有在对方关闭的时候能收到,本方关闭连接的时候你得自己处理关闭和delete
这样做好些:new的时候将新对象指针加入到一个链表中(比如窗口类中的链表),OnDestory的时候给窗口post一个消息,参数包含这类的指针,一定要post不能send,因为post是异步的,窗口收到这个消息,延时若干毫秒后,删除该对象,将其指针链表正如8楼所说,频繁分配、释放内存是不好的,记得我们在只用套接字而不是封装好的类的时候是怎么做的吗?对!定义一个用于与客户端连接的套接字数组,新有客户端连接的时候,给他们分配可用的套接字,这个数组就是“对象池”的概念,但数组的容量是固定的,你的设计应该可以在容量不足的时候使这个对象池的容量扩大,这样就可以动态的维护与多个客户端的连接,并且避免频繁的内存分配
然后再来一个队列,这个队列保存可用的(空闲的,未与客户端连接的)Socket对象指针,那么初始时全部的指针都入队列
当一个客户端请求连接的时候,出队列一个对象分配给这个客户端,比如10个。若是队列为空,那就说明当前所有的Socket对象都被用了,这时就创建一定数量的新Socket,将指针保存到列表,并入队列,这样就保证如果不够用的情况下会分配新的对象。
当一个用户断开连接的时候,将这个对象的指针重新入队列,这样用过的Socket对象就可以重复使用了这应该就是一个比较合理的方案了