soap

soap

soap是一种基于XML的简易协议,允许程序通过HTTP来交换信息,用在分散或分布的环境中交换信息。

一条soap消息就是一个普通的xml文档,包含下列元素:

l  必须的Envelope元素,标识该文档为一条soap消息;

l  可选的Header元素,用于传输头信息;

l  必需的Body元素,包含了所有的调用或响应信息;

l  可选的Fault元素,提供有关处理错误的信息;

以上的元素均被声明为针对soap封装的默认命名空间中:http://schemas.xmlsoap.org/soap/envelope/,一条soap消息如下:

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"

xmlns:q0="www.ssl.com"xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

  <soape:Body>

     <q0:add>

       <a>1</a>

       <b>2</b>

     </q0:add>

  </soape:Body>

</soape:Envelope>

1、       Header

可选的Header元素包含有关SOAP消息的应用程序相关信息,如认证、安全等。如果提供Header元素,则必须是Envelop元素的第一个子元素。

注意:所有Header元素的直接子元素必须有合格的命名空间,如下

<?xmlversion="1.0"?>

<soap:Envelope

xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"

xmlns:q0="www.ssl.com"xmlns:xsd="http://www.w3.org/2001/XMLSchema"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

 <soap:Header>

 <m:Trans xmlns:m="http://www.ssl.com">234</m:Trans> </soap:Header>

<soap:body>

  …

</soap:body>

</soap:Envelope>

2、       Body

Body元素是必须的,包含了发送或接受的信息。Body元素的直接子元素也必须有合格的命名空间,如下

<?xmlversion="1.0"?>

<soap:Envelope

xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"

xmlns:q0="www.ssl.com"xmlns:xsd="http://www.w3.org/2001/XMLSchema"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

<soap:Body>  

<m:GetPricexmlns:m="http://www.ssl.com/prices">              <m:Item>Apples</m:Item>  

  </m:GetPrice>

</soap:body>

</soap:Envelope>

该消息的响应消息如下:

<?xmlversion="1.0"?>

<soap:Envelope

xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"

xmlns:q0="www.ssl.com"xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

<soap:Body>  

<m:GetPriceResponsexmlns:m="http://www.ssl.com/prices">              <m:price>3.6</m:price>  

  </m:GetPriceResponse>

</soap:body>

</soap:Envelope>

对于body元素的非直接子元素,在消息发送和消息响应时最好统一是否增加前缀,如不一致数据接受可能会出现错误。

3、       Fault

Fault元素用于传输SOAP的错误信息。如果Fault元素存在,则必须是Body元素的子元素,在一条SOAP消息中,Fault元素只能出现一次。Fault元素有如下子元素:

l  faultcode,错误代号;

l   faultString,错误描述信息,最常用;

l  faultactor

l  detail

包含错误信息的SOAP消息如下

<?xml version='1.0'encoding='UTF-8'?>

<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/"><S:Body>

    <S:Faultxmlns:ns4="http://www.w3.org/2003/05/soap-envelope">

       <faultcode>S:Server</faultcode>

       <faultstring>没有认真信息,认证失败</faultstring>

       <detail>

         <ns2:AuthException   xmlns:ns2="http://www.ssl.com/student/">

      <message>没有认真信息,认证失败</message>

    </ns2:AuthException>

</detail>

     </S:Fault>

    </S:Body>

 </S:Envelope>

 

4、       Binding

定义了一种使用底层传输协议来完成在节点间交换SOAP信封的约定。

5、       API

SOAP消息基本上是从发送端到接收端的单向传输,常常结合起来执行类似于请求/应答的模式。一条SOAP消息就是一个普通的XML文档,其结构如下图所示,


在JAX-WS中,一条消息对应一个SOAPMessage实例。SOAPMessage封装了对soap消息的操作。WebService的本质就是SOAP消息的发送和SOAP消息的响应,所以可以通过SOAPMessage实现对webService的调用(其他相关API请参考jaxws-api),如下:

String ns="ns;

//1. 创建服务

URL ur=new URL("wsdl-address");

QName qname=new QName(ns,"WebServiceName");

Service service=Service.create(ur, qname);

          

//2、创建Dispatch

Dispatch<SOAPMessage> dispatch=service.createDispatch(new QName(ns,"WebServicePortName"),SOAPMessage.class,Service.Mode.MESSAGE);

//3、创建SOAPMessage

SOAPMessage message=MessageFactory.newInstance().createMessage();

SOAPEnvelope envelope=message.getSOAPPart().getEnvelope();

SOAPBody body=envelope.getBody();

//4、创建qname来指定消息中传递数据

//指定那个方法

QName ename=new QName(ns,"add","nn");

SOAPBodyElement element=body.addBodyElement(ename);

 element.addChildElement("a").setValue("1");

 element.addChildElement("b").setValue("2");

          

 //打印消息

 message.writeTo(System.out);

 System.out.println("\ninvoking");

          

 //5、通过dispatch传递消息

 SOAPMessage response=dispatch.invoke(message);

 response.writeTo(System.out);

 

 

 

 

/****************************************************************************** * Copyright (c) 2018-2018 TP-Link Systems Inc. * * Filename: soap.c * Version: 1.0 * Description: soap 处理函数 * Author: liyijie<liyijie@tp-link.com.cn> * Date: 2018-12-03 ******************************************************************************/ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <sys/types.h> #include <arpa/inet.h> #include "onvif_passthrough.h" #include "soap_global.h" #include "soap_parse.h" #include "soap_pack.h" #define SOAP_TAG_NUM 256 typedef struct _SOAP_TAG_HANDLE { char tag[LEN_TAG]; S32 (*handle)(SOAP_CONTEXT *soap); }SOAP_TAG_HANDLE; LOCAL SOAP_TAG_HANDLE g_soap_tag_handle[SOAP_TAG_NUM]; /****************************************************************************** * 函数名称: new_soap() * 函数描述: 申请soap结构体 * 输 入: N/A * 输 出: N/A * 返 回 值: soap结构体地址 ******************************************************************************/ SOAP_CONTEXT *new_soap() { SOAP_CONTEXT *soap = NULL; soap = (SOAP_CONTEXT *)ONVIF_MALLOC(sizeof(SOAP_CONTEXT)); if (soap == NULL) { ONVIF_ERROR("malloc g_soap_for_discv failed"); return NULL; } memset(soap, 0, sizeof(SOAP_CONTEXT)); if (OK != onvif_create_buf(&soap->xml_buf, ONVIF_DISCV_BUF_LEN)) { ONVIF_FREE(soap); return NULL; } return soap; } /****************************************************************************** * 函数名称: free_soap() * 函数描述: 释放soap结构体 * 输 入: soap -- soap结构体地址 * 输 出: N/A * 返 回 值: N/A ******************************************************************************/ void free_soap(SOAP_CONTEXT *soap) { if (soap == NULL) { return; } if (soap->fault != NULL) { ONVIF_FREE(soap->fault->soap_env_value); ONVIF_FREE(soap->fault->soap_env_subcode_1); ONVIF_FREE(soap->fault->soap_env_subcode_2); ONVIF_FREE(soap->fault->soap_env_reason); ONVIF_FREE(soap->fault); } onvif_free_buf(&soap->xml_buf); ONVIF_FREE(soap); return; } /****************************************************************************** * 函数名称: soap_init() * 函数描述: 初始化soap结构体 * 输 入: soap -- soap结构体地址 * 输 出: N/A * 返 回 值: N/A ******************************************************************************/ void soap_init(SOAP_CONTEXT *soap) { if (soap == NULL) { ONVIF_WARN("soap == NULL."); return; } soap->error = OK; soap->in_ip = 0; soap->ifindex = -1; soap->has_header = FALSE; memset(&soap->header, 0, sizeof(SOAP_ENV_HEADER)); if (soap->fault != NULL) { ONVIF_FREE(soap->fault->soap_env_value); ONVIF_FREE(soap->fault->soap_env_subcode_1); ONVIF_FREE(soap->fault->soap_env_subcode_2); ONVIF_FREE(soap->fault->soap_env_reason); ONVIF_FREE(soap->fault); soap->fault = NULL; } soap->tag[0] = '\0'; soap->request_begin = NULL; soap->request_end = NULL; soap->types[0] = '\0'; soap->scopes_item[0] = '\0'; soap->scopes_matchby[0] = '\0'; if (soap->xml_buf.start == NULL || (soap->xml_buf.end - soap->xml_buf.start) > ONVIF_DISCV_BUF_LEN) { if (OK != onvif_create_buf(&soap->xml_buf, ONVIF_DISCV_BUF_LEN)) { soap->xml_buf.start = NULL; soap->xml_buf.last = NULL; soap->xml_buf.end = NULL; } } soap->xml_buf.last = soap->xml_buf.start; return; } /****************************************************************************** * 函数名称: soap_out_env_fault() * 函数描述: 组装错误信息报文内容 * 输 入: xml_buf -- 存放输出xml字串的内存地址 * fault_data -- 错误信息 * 输 出: N/A * 返 回 值: ERROR/OK ******************************************************************************/ LOCAL S32 soap_out_env_fault(ONVIF_BUF *xml_buf, SOAP_ENV_FAULT *fault_data) { char attr[LEN_ANY] = {0}; if (xml_buf == NULL) { ONVIF_WARN("xml_buf == NULL."); return ERROR; } /* SOAP-ENV:Fault begin */ SOAP_IF_FAIL_RET(soap_element_begin_out(xml_buf, G_SOAP_ENV_FAULT_STR, NULL)); /* SOAP-ENV:Code begin */ SOAP_IF_FAIL_RET(soap_element_begin_out(xml_buf, "SOAP-ENV:Code", NULL)); /* SOAP-ENV:Value */ SOAP_IF_FAIL_RET(soap_element(xml_buf, "SOAP-ENV:Value", fault_data->soap_env_value, NULL)); if (fault_data && fault_data->soap_env_subcode_1) { /* SOAP-ENV:Subcode begin */ SOAP_IF_FAIL_RET(soap_element_begin_out(xml_buf, "SOAP-ENV:Subcode", NULL)); /* SOAP-ENV:Value */ SOAP_IF_FAIL_RET(soap_element(xml_buf, "SOAP-ENV:Value", fault_data->soap_env_subcode_1, NULL)); if (fault_data->soap_env_subcode_2) { /* SOAP-ENV:Subcode begin */ SOAP_IF_FAIL_RET(soap_element_begin_out(xml_buf, "SOAP-ENV:Subcode", NULL)); /* SOAP-ENV:Value */ SOAP_IF_FAIL_RET(soap_element(xml_buf, "SOAP-ENV:Value", fault_data->soap_env_subcode_2, NULL)); /* SOAP-ENV:Subcode end */ SOAP_IF_FAIL_RET(soap_element_end_out(xml_buf, "SOAP-ENV:Subcode")); } /* SOAP-ENV:Subcode end */ SOAP_IF_FAIL_RET(soap_element_end_out(xml_buf, "SOAP-ENV:Subcode")); } /* SOAP-ENV:Code end */ SOAP_IF_FAIL_RET(soap_element_end_out(xml_buf, "SOAP-ENV:Code")); /* SOAP-ENV:Reason begin */ SOAP_IF_FAIL_RET(soap_element_begin_out(xml_buf, "SOAP-ENV:Reason", NULL)); /* SOAP-ENV:Text */ snprintf(attr, sizeof(attr), "xml:lang=\"en\""); SOAP_IF_FAIL_RET(soap_element(xml_buf, "SOAP-ENV:Text", fault_data->soap_env_reason, attr)); /* SOAP-ENV:Reason end */ SOAP_IF_FAIL_RET(soap_element_end_out(xml_buf, "SOAP-ENV:Reason")); /* SOAP-ENV:Fault end */ SOAP_IF_FAIL_RET(soap_element_end_out(xml_buf, G_SOAP_ENV_FAULT_STR)); return OK; } /****************************************************************************** * 函数名称: soap_fault() * 函数描述: 填充错误信息结构体内容 * 输 入: soap -- soap结构体地址 * code -- 错误码 * subcode1 -- 子错误码1 * subcode2 -- 子错误码2 * reason -- 错误原因 * 输 出: N/A * 返 回 值: ERROR/OK ******************************************************************************/ S32 soap_fault(SOAP_CONTEXT *soap, char *code, char *subcode1, char *subcode2, char *reason) { ONVIF_TRACE("Onvif_fault\n"); if (soap == NULL || code == NULL || subcode1 == NULL) { ONVIF_TRACE("soap == NULL || code == NULL || subcode1 == NULL."); return ERROR; } if (soap->fault) { ONVIF_FREE(soap->fault->soap_env_value); ONVIF_FREE(soap->fault->soap_env_subcode_1); ONVIF_FREE(soap->fault->soap_env_subcode_2); ONVIF_FREE(soap->fault->soap_env_reason); } else { soap->fault = ONVIF_MALLOC(sizeof(SOAP_ENV_FAULT)); } if (NULL == soap->fault) { ONVIF_WARN("ONVIF_MALLOC fault failed."); return ERROR; } memset(soap->fault, 0, sizeof(SOAP_ENV_FAULT)); soap->fault->soap_env_value = ONVIF_STRDUP(code); if (NULL == soap->fault->soap_env_value) { ONVIF_WARN("ONVIF_STRDUP soap_env_value failed."); return ERROR; } soap->fault->soap_env_subcode_1 = ONVIF_STRDUP(subcode1); if (NULL == soap->fault->soap_env_subcode_1) { ONVIF_WARN("ONVIF_STRDUP soap_env_subcode_1 failed."); return ERROR; } if (subcode2) { soap->fault->soap_env_subcode_2 = ONVIF_STRDUP(subcode2); if (NULL == soap->fault->soap_env_subcode_2) { ONVIF_WARN("ONVIF_STRDUP soap_env_subcode_2 failed."); return ERROR; } } if (reason) { soap->fault->soap_env_reason = ONVIF_STRDUP(reason); if (NULL == soap->fault->soap_env_reason) { ONVIF_WARN("ONVIF_STRDUP soap_env_reason failed."); return ERROR; } } return OK; } /****************************************************************************** * 函数名称: soap_generate_fault() * 函数描述: 组装错误报文xml内容 * 输 入: soap -- soap结构体地址 * 输 出: N/A * 返 回 值: ERROR/OK ******************************************************************************/ LOCAL S32 soap_generate_fault(SOAP_CONTEXT *soap) { if (soap == NULL) { ONVIF_WARN("soap == NULL."); return ERROR; } //soap_set_fault(soap); if (soap->fault == NULL) { return ERROR; } if (soap->error < 200 && soap->error != SOAP_FAULT) { soap->has_header = FALSE; } return soap_generate_xml((p_out_fun)(soap_out_env_fault), soap, soap->fault); } /****************************************************************************** * 函数名称: soap_serve_request() * 函数描述: soap请求处理函数入口 * 输 入: soap -- soap结构体地址 * 输 出: N/A * 返 回 值: ERROR/OK ******************************************************************************/ S32 soap_serve_request(SOAP_CONTEXT *soap) { U32 index = 0; PASSTHROUGH_RET ret = 0; if (soap == NULL || soap->tag[0] == '\0') { return ERROR; } ret = onvif_serve_passthrough(soap); if (PASSTHROUGH_ERROR == ret) { return ERROR; } else if (PASSTHROUGH_SOAP_FAULT == ret) { SOAP_IF_FAIL_RET(soap_generate_fault(soap)); } else if (PASSTHROUGH_NOT_MATCH == ret) { for (index = 0; index < SOAP_TAG_NUM; index++) { if (NULL == g_soap_tag_handle[index].handle) { SOAP_IF_FAIL_RET(soap_fault(soap, "SOAP-ENV:Receiver", "ter:ActionNotSupported", NULL, NULL)); soap->error = SOAP_FAULT; SOAP_IF_FAIL_RET(soap_generate_fault(soap)); break; } if (soap_match_tag(soap->tag, g_soap_tag_handle[index].tag)) { if (g_soap_tag_handle[index].handle(soap)) { if (soap->fault == NULL) { soap_fault(soap, "SOAP-ENV:Sender", "ter:InvalidArgVal", NULL, "error"); soap->error = SOAP_FAULT; } SOAP_IF_FAIL_RET(soap_generate_fault(soap)); } break; } } if (index >= SOAP_TAG_NUM) { SOAP_IF_FAIL_RET(soap_fault(soap, "SOAP-ENV:Receiver", "ter:ActionNotSupported", NULL, NULL)); soap->error = SOAP_FAULT; SOAP_IF_FAIL_RET(soap_generate_fault(soap)); } } /* UDP直接回复,HTTP在上一层回复 */ if (soap->use_udp == TRUE && soap->xml_buf.start != NULL && soap->xml_buf.start != soap->xml_buf.last) { return onvif_send_udp_packet(soap->sock, soap->in_ip, soap->sin_port, soap->xml_buf.start, (soap->xml_buf.last - soap->xml_buf.start)); } return OK; } LOCAL S32 soap_env_fault_handle(SOAP_CONTEXT *soap) { if (soap == NULL) { ONVIF_WARN("soap == NULL."); return ERROR; } ONVIF_TRACE("SOAP-ENV:Fault handle."); /* do nothing and no response */ return OK; } /****************************************************************************** * 函数名称: soap_tag_handle_add() * 函数描述: 注册soap请求处理函数 * 输 入: tag -- 请求tag * handle -- 处理函数 * 输 出: N/A * 返 回 值: ERROR/OK ******************************************************************************/ void soap_tag_handle_add(char *tag, void *handle) { U32 index = 0; if ((NULL == tag) || (strlen(tag) >= 64) || (NULL == handle)) { ONVIF_ERROR("soap handle add error, invalid arg."); return; } while ((index < SOAP_TAG_NUM) && (NULL != g_soap_tag_handle[index].handle)) { index++; } if (index >= SOAP_TAG_NUM) { ONVIF_ERROR("soap handle add error, max support %d tags.", SOAP_TAG_NUM); return; } snprintf(g_soap_tag_handle[index].tag, sizeof(g_soap_tag_handle[index].tag), "%s", tag); g_soap_tag_handle[index].handle = handle; return; } /****************************************************************************** * 函数名称: soap_tag_handle_init() * 函数描述: 初始化soap请求处理函数 * 输 入: N/A * 输 出: N/A * 返 回 值: ERROR/OK ******************************************************************************/ void soap_tag_handle_init() { U32 index = 0; for (index = 0; index < SOAP_TAG_NUM; index++) { memset(g_soap_tag_handle[index].tag, 0, sizeof(g_soap_tag_handle[index].tag)); g_soap_tag_handle[index].handle = NULL; } soap_tag_handle_add("SOAP-ENV:Fault", soap_env_fault_handle); return; } ——+能不能详细地一行一行一个一个变量一个一个函数地给我解释下代码
最新发布
09-02
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值