直接用Qt写soap

最近的项目里用到了webservice, 同事用的是`gSoap`来搞的.
用这个本身没什么问题, 但这货生成的代码实非人类可读, 到处都是`__`和`_`, 看得我眼晕.....
其实项目里用的webservice很简单, 暂时只有身份验证这一个, 所以就想能不能直接用Qt搞定.
说搞就搞, 哪知一下就搞了1天半.....
把过程记录下来, 以防我的老脑筋忘记了 -_____-!

原理

我们用的webservice是基于xml的, 也叫soap.
而soap = http + xml, 所以原理就很简单了:
     用QHttp直接连服务器, 将请求的内容以指定xml格式组织好后, POST到服务端就OK了
 
怎么样, 原理很简单吧, 但对于我这个从来没写过http请求的人来说, 还是出了不少的状况.
 
* 400 Bad Request
    这个问题一般都是post写错了, 应该是大写`POST`才行.
 
* 500 interval server error
    一开始一直都是400错误, 不停的改代码的过程中, 也出了几次500错误.
 
出现这个错误, 一般都是xml的格式有误导致的, 如我看网上写的会在xml的开头添加一个`\n`, 我也加了, 结果就是这种错误.
 
** 注意事项 **
 
webservice中, 至少有两个header是必须填写的:
 
1. Content-Type
2. Content-Length
 
因为内容是xml格式的文本, 所以这两个必须写, 否则服务器无法正确解析.
 
代码
试验的时候, 用的是PyQt4写的, 所以这里就贴点这个代码吧:
 
      import sys
      from PyQt4.QtGui import *
      from PyQt4.QtCore import *
      from PyQt4.QtNetwork import *

class MainWindow(QMainWindow):

def __init__(self, parent=None):
              QMainWindow.__init__(self, parent)
              self._http = None

self.test()

def test(self):
              http = QHttp('10.88.104.158')
              self._http = http

data = '''<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <UserLogin xmlns="http://www.richfit.com/">
      <userLoginName>admin</userLoginName>
      <userPwd>123</userPwd>
      <appType>test</appType>
    </UserLogin>
  </soap:Body>
</soap:Envelope>'''

req = QHttpRequestHeader()
              req.setRequest('POST', '/3DWebGIS/Services/DataService.asmx')
              req.setValue('Host', '10.88.104.158')
              req.setValue('Content-Type', 'text/xml; charset=utf-8')
              req.setValue('Content-Length', str(len(data)))
              req.setValue('SOAPAction', '"http://www.richfit.com/UserLogin"')

self.connect(self._http, SIGNAL('requestFinished(int, bool)'), self.finish)

cnt = data.encode('utf-8')
              print http.request(req, cnt)

def test1(self):

import sys, httplib
              data = '''<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <UserLogin xmlns="http://www.richfit.com/">
      <userLoginName>admin</userLoginName>
      <userPwd>123</userPwd>
      <appType>test</appType>
    </UserLogin>
  </soap:Body>
</soap:Envelope>'''

h = httplib.HTTP('10.88.104.158')
              h.putrequest('POST', '/3DWebGIS/Services/DataService.asmx')
              h.putheader('Host', '10.88.104.158')
              h.putheader('User-Agent', 'Python post')
              h.putheader('Content-Type', 'text/xml; charset="UTF-8"')
              h.putheader('Content-length', str(len(data)))
              h.putheader('SOAPAction', '"http://www.richfit.com/UserLogin"')
              h.endheaders()
              h.send(data)

sc, sm, header = h.getreply()
              print sc, sm
              print header
              print h.getfile().read()

def finish(self, iid, ok):
              print iid, ok
              resp = self._http.lastResponse()
              print resp.statusCode(), resp.reasonPhrase()
              print str(self._http.readAll()).decode('utf-8')

app = QApplication(sys.argv)
          frm = MainWindow()
          frm.show()
          app.exec_()

 
这里其实提供了两种方式来实现soap请求的, 其中`test`是用qt的方案实现的, `test1`用的是最原始的方法实现的.
 
这里的东西在原理部分都可以对照上, 只有一点要注意一下:
 
      http = QHttp('10.88.104.158')
      h = httplib.HTTP('10.88.104.158')
 
这两句里的地址**不能**带`http://`哦!!
 
参考资料:
 

直接用Qt写soap的更多相关文章

  1. 这个程序员有点牛,现场直接用JS写了个飞机游戏,半小时吸粉三千

    程序员昨晚在b站直播的时用JavaScript代码写了一个飞机大战游戏,半小时不到粉丝关注就上千了. 今日就拿出来跟大家分享一下,对许多大佬来说做这个特效也不是很难,但是对于刚开始学习前端这方面还是有 ...

  2. Java中 util 包 Calendar类制作万年历(不用自己写方法,直接用Java写好的包中的类的方法)

    代码前需要了解的关于Calendar类的内容:      1.在util包中,首先要知道Calendar 提供了一个类方法 getInstance,以获得此类型的一个通用的对象.Calendar 的 ...

  3. Qt写Activex插件 总结

    最近写的插件功能基本完成,也遇到了一些坑,在这里记录一下. 我写的这个插件的js接口是仿造google earth的js接口,尽可能的达到与它的api一致.先从最简单的说起: 1. 导出接口中的flo ...

  4. 只用@property定义一个属性speed,子类不能直接用_speed,需要在interface的成员变量列表里写上_speed

    //写法一: @interface Person : NSObject { } @property (nonatomic, strong) NSString *name; @end @implemen ...

  5. 每日学习笔记:js中可以直接用id名调用的问题?

    在JavaScript中,标准的id选择器调用语法是: document.getElementById('myid').style.width = pc + "%"; 但是,今天发 ...

  6. 为什么是List list = new ArrayList() 而不直接用ArrayList

    为什么是List list = new ArrayList(),而不直接用ArrayList? 编程是要面向对象编程,针对抽象(接口),而非具体.List 是接口,ArrayList是实现. 实现Li ...

  7. 直接用nose进行django项目测试并输出html报告

    先说需求:1.测试django项目:2.打印测试报告(html格式)有以下几种测试方法:1.django自带的测试模块.在app目录下的tests.py文件中写测试类,类似这样: class MyTe ...

  8. less是什么?直接用css好还是less好

    问:Less是一个动态CSS语言框架,Less扩展了CSS的动态特性 [1]:从实现角度来说,直接用css看起来能方便一些,而less还要编译? [2]:技术上好像灵活,但是从使用者的角度来说,css ...

  9. Netty为什么不直接用AtomicXXX,而要用AtomicXXXFieldUpdater去更新变量呢?

    更多技术分享可关注我 前言 如果仔细阅读过Netty的线程调度模型的源码,或者NIO线程对象及其线程池的创建源码,那么肯定会遇到类似“AtomicIntegerFieldUpdater”的身影,不禁想 ...

随机推荐

  1. 【JAVA基本数据类型包装类】

    一.概述 JAVA中一共有8种数据类型,分别是byte short int long boolean float double  char,与此相对应的,有8个类与它们分别对应: byte Byte ...

  2. AngularJS讲义 - 作用域

    什么是作用域? Angular中作用域(scope)是模板以及工作的上下文环境,作用域中存放了应用模型和视图相关的回调行为.作用域是层次化结构的与相关联的DOM结构相对应.作用域可以观察表达式以及传播 ...

  3. Java Socket编程示例

    一.Socket简介: 1.什么是Socket 网络上的两个程序通过一个双向的通讯连接实现数据的交换,这个双向链路的一端称为一个Socket.Socket通常用来实现客户方和服务方的连接.Socket ...

  4. ASMCMD命令

    安装好用的rlwrap工具,在环境变量里添加如下,就能实现显示当前路径(目录),目录补全的方便功能 alias asmcmd='rlwrap -r -i asmcmd –p' asmcmd>he ...

  5. Sublime Text 3 安装Go语言相关插件gosublime

    1.打开Sublime Text,使用快捷键 ctrl+` (左上角Tab键上方,Esc键下方)或者使用菜单 View > Show Console menu,此时将出现Sublime Text ...

  6. 安卓app设计规范整理和Android APP设计篇(转)

    随着安卓智能手机不停的更新换代.安卓手机系统越来越完美,屏幕尺寸也越来越大啦!比如最近小米的miui 6的发布和魅族手机系统的更新等等. 以小米MIUI6的安卓手机来说,MIUI6进行了全新设计,坚持 ...

  7. 开发Portlet第一步:如何基于Crystal开发静态Portlet?

    当团队需要基于Crystal开发Porltet时,分为以下三部: 基于Crystal开发静态Portlet 基于将静态Portlet修改为基于测试数据的动态Portlet 将动态Portlet与动态数 ...

  8. Webbrowser中显示MHT文件

    把MHT文件存成临时文件,用WEBBROWSER的Navigate方法打开,代码如下: //从程序集中读取资源文件 Assembly asmm = Assembly.GetCallingAssembl ...

  9. BootSrap学习

    1.当row1里边有2个或多个col的时候,如果位置在后边的col的高度大于位置在前边的col,就可能会导致下一个row2在满足col-xs-*在满足和为12的情况下错乱分行.解决办法是强行给row1 ...

  10. vim使用01

    安装与基础配置 iTerm快捷操作 清屏: <C l>/<W k> 剪切: <W x> 复制: <W v> 新增窗口: <W d> 切换窗口 ...