CSDN首页 空间 新闻 论坛 Blog 下载 读书 网摘 搜索 .NET Java 视频 接项目 求职 在线学习 买书 程序员 通知
可用分押宝游戏火热进行中... 专题改版:Java Web 专题
CSDN社区
搜索 收藏 打印 关闭
CSDN社区 >  VC/MFC >  ATL/ActiveX/COM

求救~~~~!!COM+ 对象池实现的问题~~!!

楼主it_manager()2006-05-03 18:30:04 在 VC/MFC / ATL/ActiveX/COM 提问

研究摸索了一个星期了,对象池这个东西仍然没有搞定,非常的苦恼,唉~~,所以特来此发帖,恳请有经验的朋友指点和帮助.  
   
  我要做的是一个网络连接的对象池,前端应用在IIS中运行,要通过调用这个连接池对象来获得状态,参数和执行指令,所以没有办法,就只能通过COM+的这个所谓容器来实现我要达到的效果了.  
   
  看了网络上大量的资料,我也做出来了一个COM组件,也按照资料上讲的,都实现了IObjectControl接口,在组件服务中添加也正常,但发生一个怪现象,   如果我在组件服务中选择"启用对象池"并设置5个~100个连接后,前端应用在调用就会出现"自动化错误"的提示,   但如果我取消"启用对象池",前端的应用代码反而可以成功,但就是没有对象池的效果.  
   
  网上查了许多资料,似乎都没有一个完整的COM+对象池的代码例子可以参考,现在自己摸索着做,真的很难,感觉无助啊~~~~~~~~~~~~~~~~!!!     求求大家帮帮我吧,我快要崩溃了.  
   
   
  恳请大家帮忙,指点,兄弟感激不尽!!!!!!!  
   
  如果能有这样的COM+对象池代码就最好不过了. 问题点数:100、回复次数:17Top

1 楼pripor(心欲若止水,落花起涟漪)回复于 2006-05-03 21:06:55 得分 0

把具体问题写出来  
  或者贴上代码大家帮你看Top

2 楼it_manager()回复于 2006-05-08 10:11:59 得分 0

嗯,谢谢pripor,不过我的代码都是按标准的做法搞的,很简单,和标准的没什么不同:  
   
   
  头文件部分:  
  /////////////////////////////////////////////////////////////////////////////  
  //   CSSLNet  
  class   ATL_NO_VTABLE   CSSLNet   :    
  public   CComObjectRootEx<CComMultiThreadModel>,  
  public   CComCoClass<CSSLNet,   &CLSID_SSLNet>,  
  public   IDispatchImpl<ISSLNet,   &IID_ISSLNet,   &LIBID_SSLPOOLLib>  
  {  
  public:  
  CSSLNet();  
  ~CSSLNet();  
   
   
  DECLARE_REGISTRY_RESOURCEID(IDR_SSLNET)  
   
  DECLARE_PROTECT_FINAL_CONSTRUCT()  
   
  BEGIN_COM_MAP(CSSLNet)  
  COM_INTERFACE_ENTRY(ISSLNet)  
  COM_INTERFACE_ENTRY(IDispatch)  
  END_COM_MAP()  
   
  //   ISSLNet  
  public:  
  STDMETHOD(Close)();  
  STDMETHOD(Init)(/*[out,retval]*/   long   *lngRtn);  
  STDMETHOD(ConnectServer)(/*[out,retval]*/long   *lngRtn); //   建立连接  
  STDMETHOD(get_TimeOut)(/*[out,   retval]*/   long   *pVal); //    
  STDMETHOD(put_TimeOut)(/*[in]*/   long   newVal); //   超时时间  
  STDMETHOD(get_ServerIP)(/*[out,   retval]*/   BSTR   *pVal); //  
  STDMETHOD(put_ServerIP)(/*[in]*/   BSTR   newVal); //   服务器IP  
  STDMETHOD(get_Port)(/*[out,   retval]*/   long   *pVal); //  
  STDMETHOD(put_Port)(/*[in]*/   long   newVal); //   服务器端口  
  STDMETHOD(get_hSSLInfo)(/*[out,   retval]*/   long   *pVal); //  
  STDMETHOD(get_hSSL)(/*[out,   retval]*/   long   *pVal); //   SSL   Info  
  STDMETHOD(get_hSock)(/*[out,   retval]*/   long   *pVal); //   Sock  
  STDMETHOD(get_CertPath)(/*[out,   retval]*/   BSTR   *pVal); //   证书路径  
  STDMETHOD(put_CertPath)(/*[in]*/   BSTR   newVal);  
   
  private:  
  long   m_SSL;  
  long   m_SSLInfo;  
  long   m_Sock;  
  long   m_ServerPort;  
  long   m_TimeOut;  
   
  char   szServerIP[256];  
  char   szCertPath[256];  
   
  HINSTANCE   hinstDLL; //   动态链接库句柄  
   
  int InitSSL(void);  
  int   DestroySSL(void);  
  long   SSLMakeSession__(long   sockfd,long   SSLInfo,long   timeout,long   isServer);  
   
  };  
   
   
   
   
   
   
  cpp文件与对象池相关的部分(这些代码都是自动生成的,我也没有做过更改,其他的代码和对象池无关,所以就不贴出来了):  
   
  STDMETHODIMP   CSSLNet::get_TimeOut(long   *pVal)  
  {  
  *pVal   =   m_TimeOut;  
  return   S_OK;  
  }  
   
  STDMETHODIMP   CSSLNet::put_TimeOut(long   newVal)  
  {  
  m_TimeOut   =   newVal;  
  return   S_OK;  
  }  
   
  STDMETHODIMP   CSSLNet::Init(long   *lngRtn)  
  {  
  //   TODO:   Add   your   implementation   code   here  
  *lngRtn   =   InitSSL();  
  return   S_OK;  
  }  
   
  STDMETHODIMP   CSSLNet::Close()  
  {  
  //   TODO:   Add   your   implementation   code   here  
  DestroySSL();  
  return   S_OK;  
  }  
  Top

3 楼it_manager()回复于 2006-05-08 10:13:24 得分 0

请大家帮帮我啊~~     唉,搞这个东西,视力这几天都下降了,太压抑了~~~  
   
  痛苦啊,5.1没有休息一天,一直搞这个~~Top

4 楼it_manager()回复于 2006-05-08 10:15:15 得分 0

微软的MSDN也看过了,唉,发现搞微软的东西就是麻烦,什么东西都不确定,还是基于java的开发方便一些,资料也多,不确定的问题也少一些,微软啊,什么时候能让你的追随者不再痛苦和无奈?Top

5 楼Pipi0714(老顽童)回复于 2006-05-08 10:23:29 得分 40

www.codeproject.com上找找  
  Top

6 楼it_manager()回复于 2006-05-08 10:24:52 得分 0

前面的代码贴错了,贴成不支持pool模式的代码了,代码如下:  
   
  //==================================================  
  //头文件部分:  
  //==================================================  
   
  class   ATL_NO_VTABLE   CSSLNet   :    
  public   CComObjectRootEx<CComMultiThreadModel>,  
  public   CComCoClass<CSSLNet,   &CLSID_SSLNet>,  
  public   IObjectControl,       ////   POOL   ////  
  public   IDispatchImpl<ISSLNet,   &IID_ISSLNet,   &LIBID_SSLPOOLLib>  
  {  
  public:  
  CSSLNet();  
  ~CSSLNet();  
   
   
  DECLARE_REGISTRY_RESOURCEID(IDR_SSLNET)  
   
  DECLARE_PROTECT_FINAL_CONSTRUCT()  
   
  BEGIN_COM_MAP(CSSLNet)  
  COM_INTERFACE_ENTRY(ISSLNet)  
  COM_INTERFACE_ENTRY(IObjectControl)     ////   POOL   ////  
  COM_INTERFACE_ENTRY(IDispatch)  
  END_COM_MAP()  
   
  //   ISSLNet  
  public:  
  STDMETHOD(Activate)(); ////   POOL   ////  
  STDMETHOD_(BOOL,   CanBePooled)(); ////   POOL   ////  
  STDMETHOD_(void,   Deactivate)(); ////   POOL   ////  
   
  CComPtr<IObjectContext>   m_spObjectContext; ////   POOL   ////  
   
  STDMETHOD(Close)();  
  STDMETHOD(Init)(/*[out,retval]*/   long   *lngRtn);  
  STDMETHOD(ConnectServer)(/*[out,retval]*/long   *lngRtn); //   建立连接  
  STDMETHOD(get_TimeOut)(/*[out,   retval]*/   long   *pVal); //    
  STDMETHOD(put_TimeOut)(/*[in]*/   long   newVal); //   超时时间  
  STDMETHOD(get_ServerIP)(/*[out,   retval]*/   BSTR   *pVal); //  
  STDMETHOD(put_ServerIP)(/*[in]*/   BSTR   newVal); //   服务器IP  
  STDMETHOD(get_Port)(/*[out,   retval]*/   long   *pVal); //  
  STDMETHOD(put_Port)(/*[in]*/   long   newVal); //   服务器端口  
  STDMETHOD(get_hSSLInfo)(/*[out,   retval]*/   long   *pVal); //  
  STDMETHOD(get_hSSL)(/*[out,   retval]*/   long   *pVal); //   SSL   Info  
  STDMETHOD(get_hSock)(/*[out,   retval]*/   long   *pVal); //   Sock  
  STDMETHOD(get_CertPath)(/*[out,   retval]*/   BSTR   *pVal); //   证书路径  
  STDMETHOD(put_CertPath)(/*[in]*/   BSTR   newVal);  
   
  private:  
  long   m_SSL;  
  long   m_SSLInfo;  
  long   m_Sock;  
  long   m_ServerPort;  
  long   m_TimeOut;  
   
  char   szServerIP[256];  
  char   szCertPath[256];  
   
  HINSTANCE   hinstDLL; //   动态链接库句柄  
   
  int InitSSL(void);  
  int   DestroySSL(void);  
  long   SSLMakeSession__(long   sockfd,long   SSLInfo,long   timeout,long   isServer);  
   
  };  
   
   
  //==================================================  
  //CPP文件部分:  
  //==================================================  
   
  STDMETHODIMP   CSSLNet::get_TimeOut(long   *pVal)  
  {  
  *pVal   =   m_TimeOut;  
  return   S_OK;  
  }  
   
  STDMETHODIMP   CSSLNet::put_TimeOut(long   newVal)  
  {  
  m_TimeOut   =   newVal;  
  return   S_OK;  
  }  
   
  STDMETHODIMP   CSSLNet::Init(long   *lngRtn)  
  {  
  //   TODO:   Add   your   implementation   code   here  
  *lngRtn   =   InitSSL();  
  return   S_OK;  
  }  
   
  STDMETHODIMP   CSSLNet::Close()  
  {  
  //   TODO:   Add   your   implementation   code   here  
  DestroySSL();  
  return   S_OK;  
  }  
   
   
  HRESULT   CSSLNet::Activate()  
  {  
  HRESULT   hr   =   GetObjectContext(&m_spObjectContext);  
  if   (SUCCEEDED(hr))  
  return   S_OK;  
  return   hr;  
   
  }    
   
  BOOL   CSSLNet::CanBePooled()  
  {  
  return   TRUE;  
  }    
   
  void   CSSLNet::Deactivate()  
  {  
  m_spObjectContext.Release();  
  }    
   
   
   
  之所以发出上面的感叹,是因为我完全按照MSDN和网络上关于对象池COM+对象的例子去建立和实现,没有做任何添加和改动,结果和我提到的问题一样,所以现在感觉微软的MSDN就是在放屁.Top

7 楼Pipi0714(老顽童)回复于 2006-05-08 10:25:06 得分 0

看看这个网址的有例子代码:搞底层的东西需要的知识越多  
   
   
  http://comcamp.diy.myrice.com/techarticles/com/2011.htmTop

8 楼it_manager()回复于 2006-05-08 10:26:26 得分 0

谢谢Pipi0714   老顽童,  
   
  codeproject我找过了,并没有发现有com+的例子,并且对于com+对象池的例子所有开源站点都非常少,   codeproject有个关于com+连接池的文章我倒是看过了,但没什么用,都是概念性的叙述,没有实际的代码...Top

9 楼it_manager()回复于 2006-05-08 10:27:42 得分 0

嗯.多谢多谢,真的感谢,我先看看Top

10 楼horris(僧推月下门)回复于 2006-05-09 17:15:32 得分 60

你没有好好看文档,仅从贴上来的代码看,有很多基础知识都不懂。  
  1。组件类的所有方法、属性在返回前,都应调用IObjectContext::SetComplete :  
  m_spObjectContext->SetComplete(...)  
  不这么做,JIT就不起作用,你的组件实例就不会被去激活,也就不会被放回池中供其实客户端使用。  
  2。要记住,组件类的所有数据成员都可能被其它客户端使用,所以数据成员不要存储特定于某个客户端的信息。  
  3。组件类的所有数据成员都要有同步保护,因为可池装对象有可能被多个线程同时访问,也就是说,可能有多个线程同时读、写一个组件实例的同一个数据成员。  
  4。建议把.rgs文件中的ThreadModel改为Free或Neutral。Top

11 楼it_manager()回复于 2006-05-09 18:23:57 得分 0

感谢horris的回复,   下载了Pipi0714(老顽童)   给的代码后,问题基本上解决了.  
   
  我原来没接触过com+,确实因为应用需要,才开始弄,时间紧张,具体细节也没多看,见笑了.但对于horris提到的第1点,所有组件类方法,属性返回前都必须调用setcomplete(),这个我有些不大明白,我现在的com+组件似乎没这么处理,经过测试,也能有池化的效果?     至于2,3点,这些我倒是注意到了.   至于第4点,我采取的是both方式,这个从资料上的说明来看,好像也是种不错的选择?  
   
   
  另外还有个问题,恳请   horris   和   老顽童   关注一下,再次感谢:  
   
  不知两位是否有做过IIS的应用?   我现在要在IIS中实现一个全局的公共对象,似乎IIS除了采取COM+组件容器,没有别的办法了?   但COM+通过今天的测试,发现效果并不理想,因为这样大大降低了我前端应用的效率.  
   
  不知道结合IIS有没有类似tomcat或者weblogic一样的应用容器?   或者我可以自己定义代码写一个ASP的运行容器?   只要达到全局共享一个公共对象就可以了(访问互斥和同步这个对象来处理).  
   
  开始也试过用IIS中内置的APPLICATION来存储对象,正如微软所提到的,这样不是个好办法,最终会造成串行效果,我通过测试工具在模拟100个用户同时访问的情况下,所有的处理都阻塞在Application的对象获取上了,所以后来没法,就考虑采取COM+.  
   
   
   
  非常感谢2位高手的热情帮助,感激不尽,如有机会,很想认识2位(记得我原来提过几次问题,2位也有过解答),   我的QQ号:   40297952   ,如果方便,麻烦加一下我.Top

12 楼horris(僧推月下门)回复于 2006-05-11 11:33:24 得分 0

我提的1,是我的实践经验,而且有MSDN为证,必须这么做,除非你在COM+中定义了方法级强制JIT。  
  至于4,如果设为Both的话,那么当STA客户端调用你的组件时,组件将在一个对应于该客户端的STA中创建,这样其他客户端在使用这个组件实例时,就会发生线程切换以及调用阻塞,极大影响性能,失去了池装对象的意义。  
  对于你的IIS情形,应该不会有那么大的性能损失,你实行我提的1和4再试试。Top

13 楼it_manager()回复于 2006-05-31 11:52:23 得分 0

谢谢楼上horris的回复,出差才回来,抱歉到现在还没有结帖,非常感谢2位的热情帮助.  
   
  现在采纳了horris的建议进行改进和处理后,速度确实快了,基本上能满足我的应用了,但又遇到了新的问题,还望2位再次指点,给些建议,非常感谢:  
   
  因为我做的这个对象池主要任务是建立SSL的网络连接,对象池实现后,对象被回收后,其连接并没有断开,但服务器端会因为连接长时间没有活动而自动断开,所以我就在想,是否可以在COM组件中做一个轮询的服务,隔一段时间自动在空闲的时候去发送一个NOOP指令,以维护这样一个网络连接,不知道这样是否可以实现?  
   
  还有就是,如果轮询服务发现当前连接已经不再可用,或者遇到不可恢复的故障时,是否可以自己将自身彻底从池中删除掉?   而不是重新放回池中?  
   
  恳请2位解答,多谢!!!Top

14 楼horris(僧推月下门)回复于 2006-05-31 12:02:29 得分 0

对于池装组件将自身从池中删除,我不了解有什么方法,你可以看看COMAdmin库,这是一套管理COM+应用的API,操作系统的交互式管理工具“组件服务”中有的功能它都可以实现,而且还能做后者不能做的工作。  
  你还可以试试整新回收整个COM+应用的进程。  
  对于轮询,我想这就需要你在服务器端做一个服务或任务计划。还有一个方案,就是在组件自身产生一个线程,这个线程做轮询的工作。这样做的话,建议你最好把COM+应用设置为“空闲时保持运行”(通过属性的“高级”夹)。Top

15 楼it_manager()回复于 2006-06-22 09:37:50 得分 0

horris,你好,感谢您的回复.  
   
  用COM+总算实现了对象池,并且也经过了一般性的压力测试,但在win2003上进行部署变得不稳定,感觉是心力焦瘁了.  
   
  win2000上通过了完整的压力测试,一切运行正常,我在此COM+对象中通过定时器实现了永久保持连接,并且加上了非常多的容错功能,   但在win2003上问题变得麻烦了,安装后重新启动后,COM+对象都能正常被调用,池化,但一旦关闭COM+对象或者组件中的异常错误,就再也无法启动,除非重新启动计算机.感觉真是无法摸透微软平台的东西,2000上非常稳定,但同样的东西在2003上就变得不可控了,而且系统日志中也没有任何错误信息.  
   
  望能得到您的指点,这恐怕是我仅存的一线希望了,多谢!!!!!!!!Top

16 楼horris(僧推月下门)回复于 2006-06-24 00:33:03 得分 0

应该是程序中实现永久保持连接的部分有BUG,可能你在Win2000上并没有仔细作测试。Top

17 楼it_manager()回复于 2006-07-12 09:54:28 得分 0

horris:  
   
  再次感谢您的指导,从您的回复中我找到了具体的问题,是因为我所采用的openssl底层代码中调用的临界段函数在win2003上工作不正常导致的,我采用事件的方式替代解决了这一问题。  
   
  呵呵,现在我做的部分已经通过不同平台(XP,WIN2000,WIN2003,2000   SERVER等)的压力测试,效果还不错,感慨颇多,系统运行的效果还是蛮不错的。另外我还根据您前面提到的组件服务COM组件实现了对组件应用添加删除以及所有的操作,全部可以通过程序来控制和实现。  
   
  感叹CSDN这个平台,也很佩服和感谢horris这样的高手,说大点讲得上是义举了,说真的,当初的迷茫和苦恼能通过CSDN,得到horris的帮助而化解,心情很复杂,哈哈。。。  
   
  向horris致敬!   感谢帮助!    
   
  BTW,以后其他人有任何需要COM+对象池类似的技术问题帮助,也可以发消息给我。学不到horris那样高的水平,这个精神和行为我还是可以学到的。呵呵  
   
  Top

相关问题

关键词

得分解答快速导航

  • 帖主:it_manager
  • Pipi0714
  • horris

相关链接

  • Visual C++类图书
  • Visual C++类源码下载

广告也精彩

反馈

请通过下述方式给我们反馈
反馈
提问
网站简介|广告服务|VIP资费标准|银行汇款帐号|网站地图|帮助|联系方式|诚聘英才|English|问题报告
世纪乐知(北京)网络技术有限公司 版权所有, 京 ICP 证 020026 号
北京创新乐知广告有限公司 提供技术支持
Copyright © 2000-2007, CSDN.NET, All Rights Reserved
GongshangLogo