zoukankan      html  css  js  c++  java
  • VC非托管代码调用webservice,并支持代理服务器设置

    这是这几天里我同时解决的另一个问题。

    我用的是VC2003,在非托菅的本机代码中调用webservice时,很有一些令人糊涂的地方,在这里记下来,以后也方便自己回忆。

     方法:

    1.增加webservice引用。

    2.自动生成代理类。

    上面简单。但当看着所生成的代理类时,多年没碰过VC代码的我哭了……VC的代理类是下面这样的:

     template <typename TClient = CSoapSocketClientT<> >

    class CWebService1T : 
    public TClient, 
    public CSoapRootHandler
    {
    。。。

    }

    模板套模板。。。

    嘛意思?

    意思是:代理类在实例化时,要指定一个网络客户端工具类。默认这个类是CSoapSocketClientT<>, 这也是一个模板类。

    template <typename TSocketClass = ZEvtSyncSocket>
    class CSoapSocketClientT

    { 。。。}

    看,默认的默认类是ZEvtSyncSocket,这是个啥类我实在没有心情去研究,看名字是一个Sock通讯类。不要不要!

    那么调用webservice方法仲么办? 要这样:

     CWebService1T<CSoapWininetClient> proxy = new CWebService1T<CSoapWininetClient>;

    proxy->SetUrl("http://xxx.com/Webservice1.asmx");  

    proxy->HelloWork();

    这里我没有用VC神经乎乎地推荐的那个 CSoapSocketClientT<ZEvtSyncSocket>, 而是用了CSoapWininetClient类做为工具类(atlsoap.h)。

    注意上面的代码,有一个SetUrl的方法调用,这个方法你一定在代理类中找不到,但是编译运行又都正常。奇怪不? 

     请您这时候再回去注意一下CWebService1T的定义,CSoapWininetClient被置换为TClient泛型参数,而TClient又被放在了类定义的冒号后面,啥意思?

    就是说你代入的这个模板参数类型将是代理类的父类呀!简直把人绕晕了!

     也就是说,我写CWebService1T<CSoapWininetClient> proxy 时,CSoapWininetClient将是CWebService1T<>的基类!CSoapWininetClient有SetUrl, SetProxy等方法,所以proxy 也就可以调用这些方法了。

    因为 CSoapWininetClient是用了Wininet.dll库的api进行通信的,这个库的特点就是支持http,而且和ie的设置是相通的,因此,用了这个工具类,你的proxy对象就可以透过代理服务器调用webserivce了。

    一切问题都解决了?没有。

    我这两天遇上了几个做难死人的问题——一个客户的网络需要用代理服务器上网,而且是需要输入口令的。

    本来这个问题也不是问题,只要ie能上网,在代理服务器要口令时,输入口令并选一下保存密码的复选框,这个用户凭据就会记录在系统中, CSoapWininetClient就可以自动取用,  很多客户的网络环境都是这样的,我们的客户端程序运行得很好。

    但是不幸的是,这个客户的机器被设置了策略,就算是在ie里选了保存密码的复选框,密码也不能保存下来,每次打开ie时,都需要重新输入口令。

    既然系统里没有用户凭据,CSoapWininetClient也就没有办法从ie得到用户名与口令。

    我研究了CSoapWininetClient这个类,可恨的是这个类没有任何事件、callback、委托等扩展渠道让我在合适地地方切进去,设置那些代理啦、用户名啦口令啦什么的。在代理类调用hellowork时,就调用CSoapWininetClient的第一个方法就是SendRequest方法,在这个方法里,它打开对话,建立连接,Post数据、得到回应的流,一气呵成了!中间没有用户的机会加入代码。

    我发愁了老半天,决定从 CSoapWininetClient派生一个子类来用,想试试能不能通过重载一下某些方法来介入自己的代码。这叫什么模式来着?装饰类?

    结果发现这个类里很多粉重要的方法、成员都是private的,没法引用。

    真没有办法了?我暴怒了!我和他拼了!我把 CSoapWininetClient类的源代码全拷贝出来,在项目里建了一个新类,叫CFuckedSoapWininetClient, 然后把CSoapWininetClient类的所有内容都复制了进去,现在,你是我的啦!哇哈哈!

    再把调用Webservice的代码改一下,把参数类名改为Fuck过的新类。

     CWebService1T<CFuckedSoapWininetClient> proxy = new CWebService1T<CFuckedSoapWininetClient>;

    proxy->SetUrl("http://xxx.com/Webservice1.asmx");  

    proxy->HelloWork(); 

    编译,通过。运行,通过!


    现在,通信类是我的了,任我哪啥了!想加代理服务器支持,那是易如翻掌了。

    有关 代理服务器支持 功能的实现,请参考另一篇文章 http://www.cnblogs.com/haoxiaobo/archive/2012/01/09/2317559.html

     
  • 相关阅读:
    Spring 学习笔记
    Java Web整合开发(33) -- SSH和SSJ
    2、常用操作
    jsonp使用
    PHP curl 封装 GET及POST方法很不错的
    浅谈CSRF攻击方式 转
    谷歌插件请求ci 解决CI框架的Disallowed Key Characters错误提示
    phpstorm10.0.3 下载与激活
    Mysql全文搜索match against的用法
    CentOS 6.4下编译安装MySQL 5.6.14 (转)
  • 原文地址:https://www.cnblogs.com/haoxiaobo/p/2317589.html
Copyright © 2011-2022 走看看