激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - C/C++ - C++中gSOAP的使用詳解

C++中gSOAP的使用詳解

2022-02-20 14:29time-flies C/C++

這篇文章主要介紹了C++中gSOAP的使用詳解,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧

本文主要介紹C++中gSOAP的使用方法,附帶介紹SOAP協議的基礎知識,適用于第一次使用gSOAP的開發人員。gSOAP官網上的示例代碼存在一些錯誤,對初次接觸的人不太友好,本文是在官方示例calc++的基礎上進行了一些補充、改動。

 

SOAP簡介

SOAP 是一種簡單的基于 XML 的協議,它使應用程序通過 HTTP 來交換信息,具體內容可以參考SOAP 教程。SOAP的本質是通過HTTP協議以XML格式進行數據交互,只不過這個XML格式的定義是大家公認的。

使用SOAP時需注意,SOAP的XML命名空間由于版本的不同可能存在差異(如soapevn、SOAP-ENV),在調用SOAP服務前最好確認服務器的XML格式。

 

gSOAP

gSOAP 有商業版、開源版兩個版本,開源版使用GPLv2開源協議,支持多個操作系統,具體內容參考github或者官網

gSOAP提供了一組編譯工具(可以認為是代碼生成器)和一些庫文件,簡化C/C++語言開發web服務或客戶端程序的工作,開發人員可以專注于實現應用程序的邏輯:

  • 編譯工具提供了一個SOAP/XML 關于C/C++ 語言的實現,能夠自動完成本地C或C++數據類型和XML數據結構之間的轉換。
  • 庫文件提供了SOAP報文生成、HTTP協議通訊的實現,及相關的配套設施,用于最終的SOAP報文的生成、傳輸。

本文使用的庫文件主要是以下幾個:

  • stdsoap2.h、stdsoap2.cpp:HTTP協議的實現、最終的SOAP報文生成,如果是C語言則使用stdsoap2.h、stdsoap2.c
  • typemap.dat: wsdl2h工具根據wsdl文件生成頭文件時需要此文件,可以更改項目的xml命名空間(后面再細說)
  • threads.h:實現高性能的多線程服務器需要的文件,可以并發處理請求,并且在服務操作變得耗時時不會阻塞其他客戶端請求

準備工作

先進入官網的下載頁面,然后選擇開源版本:

C++中gSOAP的使用詳解

也可以直接點擊開源版本的官方下載鏈接或https://pan.baidu.com/s/156PEw9OMbzQel39Oozknow提取碼: gy4x。

將下載的壓縮包解壓(本文使用的是gsoap_2.8.117.zip),解壓后的文件放到自己習慣的位置(推薦放到C盤)。

在命令行提示符窗口中,使用cd命令進入..\gsoap_2.8.117\gsoap-2.8\gsoap\bin\win64目錄:

C++中gSOAP的使用詳解

注:后面需要把頭文件、typemap.dat放到該程序目錄下,生成的文件也在這里。

頭文件

使用gSOAP的編譯工具生成代碼,需要一個定義API的頭文件,此處使用官方示例中的calc.h頭文件,對兩個數字進行加、減、乘、除或乘方運算:。

calc.h頭文件可以通過wsdl2h工具自動生成(需要Web 服務的 WSDL文件 ),運行的cmd命令如下:

wsdl2h -o calc.h http://www.genivia.com/calc.wsdl

也可以手動定義一個calc.h頭文件,內容如下:

//gsoap ns service method add Sums two values
int ns__add(double a, double b, double &result);
//gsoap ns service method sub Subtracts two values
int ns__sub(double a, double b, double &result);
//gsoap ns service method mul Multiplies two values
int ns__mul(double a, double b, double &result);
//gsoap ns service method div Divides two values
int ns__div(double a, double b, double &result);
//gsoap ns service method pow Raises a to b
int ns__pow(double a, double b, double &result);

構建客戶端應用程序

客戶端應用程序在命令行中運行并使用命令行參數調用計算器 Web 服務來對兩個數字進行加、減、乘、除或乘方運算。

生成soap源碼

為客戶端生成服務和數據綁定接口:

soapcpp2 -j -r -CL calc.h

其中 option-j生成 C++ 代理類,option-r生成報告,option-CL僅生成客戶端,而沒有(未使用的)lib 文件。

這會生成以下幾個文件:

C++中gSOAP的使用詳解

其中,xml文件是SOAP報文的示例,便于后期的調試,以add方法為例。

add方法的請求報文ns.add.req.xml內容如下:

<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope
  xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
  xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:xsd="http://www.w3.org/2001/XMLSchema"
  xmlns:ns="http://tempuri.org/ns.xsd">
<SOAP-ENV:Body>
<ns:add>
 <a>0.0</a>
 <b>0.0</b>
</ns:add>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

add方法的響應報文ns.add.req.xml內容如下:

<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope
  xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
  xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:xsd="http://www.w3.org/2001/XMLSchema"
  xmlns:ns="http://tempuri.org/ns.xsd">
<SOAP-ENV:Body>
<ns:addResponse>
 <result>0.0</result>
</ns:addResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

建立客戶端項目

建立一個C++的控制臺應用項目,引入上面生成的幾個文件:

  • soapStub.h: 沒有注釋的純 C/C++ 頭文件語法的規范副本。
  • soapH.h:聲明 XML 序列化程序。
  • soapC.cpp: 實現 XML 序列化程序。
  • soapProxy.h: 定義客戶端 XML 服務 API 類Proxy。
  • soapProxy.cpp: 實現客戶端 XML 服務 API 類Proxy。
  • calc.nsmap: XML 命名空間綁定表到 #include。

還需要引入gSOAP解壓目錄下的stdsoap2.h和stdsoap2.cpp文件。

為方便調試,客戶端程序示例改為固定參數調用add方法,代碼如下:

#include "soapProxy.h"
#include "ns.nsmap"
/* the Web service endpoint URL */
const char server[] = "http://localhost:8080";
int main(int argc, char** argv)
{    
  /*if (argc < 4)
  {
      fprintf(stderr, "Usage: [add|sub|mul|div|pow] num num\n");
      exit(1);
  }*/
  Proxy calc(server);
  double a, b, result;
  /*a = strtod(argv[2], NULL);
  b = strtod(argv[3], NULL);*/
  a = 3;
  b = 23;
  /*switch (*argv[1])*/
  switch ('a')
  {
  case 'a':
      calc.add(a, b, result);
      break;
  case 's':
      calc.sub(a, b, result);
      break;
  case 'm':
      calc.mul(a, b, result);
      break;
  case 'd':
      calc.div(a, b, result);
      break;
  case 'p':
      calc.pow(a, b, result);
      break;
  default:
      fprintf(stderr, "Unknown command\n");
      exit(1);
  }
  if (calc.soap->error)
      calc.soap_stream_fault(std::cerr);
  else
      std::cout << "result = " << result << std::endl;
  calc.destroy(); /* clean up */
  std::cout << std::endl;
  return 0;
}

構建服務端應用程序

實現一個獨立的迭代服務器,它接受主機端口上的傳入請求,支持多線程,可以并發處理請求,并且在服務操作變得耗時時不會阻塞其他客戶端請求。

生成SOAP源碼

為服務器端生成服務和數據綁定接口:

soapcpp2 -j -r -SL calc.h

其中 option-j生成 C++ 服務類,option-r生成報告,option-SL僅生成服務器端,而沒有(未使用的)lib 文件。

生成的文件和客戶端的文件名稱一樣,只是內容不同。

建立服務端項目

建立一個C++的控制臺應用項目,引入的生成文件和客戶端的相同。為了支持多線程,需要引入文件threads.h。
服務端代碼如下:

#include "soapService.h"
#include "ns.nsmap"
#include "threads.h"
int port = 8080;
void* process_request(void* arg)
{
  Service* service = (Service*)arg;
  THREAD_DETACH(THREAD_ID);
  if (service)
  {
      service->serve();
      service->destroy(); /* clean up */
      delete service;
  }
  return NULL;
}
int main()
{
  Service service(SOAP_IO_KEEPALIVE);                      /* enable HTTP kee-alive */
  service.soap->send_timeout = service.soap->recv_timeout = 5; /* 5 sec socket idle timeout */
  service.soap->transfer_timeout = 30;                         /* 30 sec message transfer timeout */
  SOAP_SOCKET m = service.bind(NULL, port, 100);              /* master socket */
  if (soap_valid_socket(m))
  {
      while (soap_valid_socket(service.accept()))
      {
          THREAD_TYPE tid;
          void* arg = (void*)service.copy();
          /* use updated THREAD_CREATE from plugin/threads.h https://www.genivia.com/files/threads.zip */
          if (arg)
              while (THREAD_CREATE(&tid, (void* (*)(void*))process_request, arg))
                  Sleep(1);
      }
  }
  service.soap_stream_fault(std::cerr);
  service.destroy(); /* clean up */
  return 0;
}
/* service operation function */
int Service::add(double a, double b, double& result)
{
  result = a + b;
  return SOAP_OK;
}
/* service operation function */
int Service::sub(double a, double b, double& result)
{
  result = a - b;
  return SOAP_OK;
}
/* service operation function */
int Service::mul(double a, double b, double& result)
{
  result = a * b;
  return SOAP_OK;
}
/* service operation function */
int Service::div(double a, double b, double& result)
{
  if (b)
      result = a / b;
  else
      return soap_senderfault("Division by zero", NULL);
  return SOAP_OK;
}
/* service operation function */
int Service::pow(double a, double b, double& result)
{
  result = ::pow(a, b);
  if (soap_errno == EDOM)   /* soap_errno is like errno, but portable */
      return soap_senderfault("Power function domain error", NULL);
  return SOAP_OK;
}

打印報文

在實際調試中,需要確定SOAP協議過程中具體的報文,只需要改動stdsoap2.cpp源碼即可。參考gsoap報文打印,實現保存最后一次報文到特定的文件。

在stdsoap2.h頭文件include下添加fstream,內容如下:

#include "stdsoap2.h"
#include <fstream>

soap_begin_recv函數開始處添加以下代碼:

//發送完請求報文 獲取請求報文信息(作為客戶端的時候)
std::string str_reqXml = "";
std::string strBuf;
std::string::size_type pos1 = std::string::npos;
std::string::size_type pos2 = std::string::npos;
strBuf = soap->buf;
pos1 = strBuf.find("<?xml", 0);
pos2 = strBuf.find("</SOAP-ENV:Envelope>", 0);
if (pos1 != std::string::npos && pos2 != std::string::npos)
{
  str_reqXml = strBuf.substr(pos1, pos2 - pos1 + 20);
}
std::ofstream  outfile;
outfile.open("reqXml.txt");
outfile << str_reqXml;
outfile.close();

soap_body_end_in函數開始處添加以下代碼:

//接收完應答報文 獲取應答報文信息(作為客戶端的時候)
std::string str_resXml = "";
std::string strBuf;
std::string strEnd = "</SOAP-ENV:Envelope>";
std::string::size_type pos1 = std::string::npos;
std::string::size_type pos2 = std::string::npos;
pos1 = std::string::npos;
pos2 = std::string::npos;
soap->buf[SOAP_BUFLEN - 1] = '\0';
strBuf = soap->buf;
pos1 = strBuf.find("<?xml", 0);
pos2 = strBuf.find(strEnd, 0);
if (pos1 != std::string::npos && pos2 != std::string::npos)
{
  str_resXml = strBuf.substr(pos1, pos2 - pos1 + strEnd.length());
}
std::ofstream  outfile;
outfile.open("resXml.txt");
outfile << str_resXml;
outfile.close();

soap_recv_raw函數結尾處(return前)添加以下代碼:

//請求報文(作為服務端的時候)
std::string req_data;
req_data.assign(soap->buf, ret);
std::ofstream  outfile;
outfile.open("req_data.txt");
outfile << req_data;
outfile.close();

soap_flush_raw函數結尾處(return前)添加以下代碼:

//應答報文(作為服務端的時候)
std::string res_data;
res_data.assign(s, n);
std::ofstream  outfile;
outfile.open("res_data.txt");
outfile << res_data;
outfile.close();

注:客戶端可以一直打印報文,服務端只能在Debug運行時才會打印報文,應該有其它方法可以解決。

 

SOAP測試

運行上面的服務器、客戶端項目,可以看到運行API調用結果,也可以使用SoapUI進行測試。

進入官網的下載鏈接:https://www.soapui.org/downloads/soapui/,下載開源版本并安裝。

打開軟件,在菜單欄的“File”中選擇“New SOAP Project”:

C++中gSOAP的使用詳解

展開左側的項目,雙擊“Request”,開始進行測試:

C++中gSOAP的使用詳解

C++中gSOAP的使用詳解

 

項目源碼

SoapTest提取碼: 89mu

 

總結

本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關注服務器之家的更多內容!

原文鏈接:https://www.cnblogs.com/timefiles/p/CppGSoap.html

延伸 · 閱讀

精彩推薦
  • C/C++詳解c語言中的 strcpy和strncpy字符串函數使用

    詳解c語言中的 strcpy和strncpy字符串函數使用

    strcpy 和strcnpy函數是字符串復制函數。接下來通過本文給大家介紹c語言中的strcpy和strncpy字符串函數使用,感興趣的朋友跟隨小編要求看看吧...

    spring-go5642021-07-02
  • C/C++C/C++經典實例之模擬計算器示例代碼

    C/C++經典實例之模擬計算器示例代碼

    最近在看到的一個需求,本以為比較簡單,但花了不少時間,所以下面這篇文章主要給大家介紹了關于C/C++經典實例之模擬計算器的相關資料,文中通過示...

    jia150610152021-06-07
  • C/C++C語言實現電腦關機程序

    C語言實現電腦關機程序

    這篇文章主要為大家詳細介紹了C語言實現電腦關機程序,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下...

    xiaocaidayong8482021-08-20
  • C/C++學習C++編程的必備軟件

    學習C++編程的必備軟件

    本文給大家分享的是作者在學習使用C++進行編程的時候所用到的一些常用的軟件,這里推薦給大家...

    謝恩銘10102021-05-08
  • C/C++深入理解goto語句的替代實現方式分析

    深入理解goto語句的替代實現方式分析

    本篇文章是對goto語句的替代實現方式進行了詳細的分析介紹,需要的朋友參考下...

    C語言教程網7342020-12-03
  • C/C++C語言中炫酷的文件操作實例詳解

    C語言中炫酷的文件操作實例詳解

    內存中的數據都是暫時的,當程序結束時,它們都將丟失,為了永久性的保存大量的數據,C語言提供了對文件的操作,這篇文章主要給大家介紹了關于C語言中文件...

    針眼_6702022-01-24
  • C/C++C++之重載 重定義與重寫用法詳解

    C++之重載 重定義與重寫用法詳解

    這篇文章主要介紹了C++之重載 重定義與重寫用法詳解,本篇文章通過簡要的案例,講解了該項技術的了解與使用,以下就是詳細內容,需要的朋友可以參考下...

    青山的青6062022-01-04
  • C/C++c++ 單線程實現同時監聽多個端口

    c++ 單線程實現同時監聽多個端口

    這篇文章主要介紹了c++ 單線程實現同時監聽多個端口的方法,幫助大家更好的理解和學習使用c++,感興趣的朋友可以了解下...

    源之緣11542021-10-27
Weibo Article 1 Weibo Article 2 Weibo Article 3 Weibo Article 4 Weibo Article 5 Weibo Article 6 Weibo Article 7 Weibo Article 8 Weibo Article 9 Weibo Article 10 Weibo Article 11 Weibo Article 12 Weibo Article 13 Weibo Article 14 Weibo Article 15 Weibo Article 16 Weibo Article 17 Weibo Article 18 Weibo Article 19 Weibo Article 20 Weibo Article 21 Weibo Article 22 Weibo Article 23 Weibo Article 24 Weibo Article 25
主站蜘蛛池模板: 一级做a爱片毛片免费 | 国产精品1区,2区,3区 | 精品久久久久久久久中文字幕 | 亚洲综合视频一区 | av免费不卡国产观看 | 97色在线观看免费视频 | 青青草最新网址 | 日韩在线欧美在线 | 成人三级电影在线 | 永久在线观看电影 | 精品久久久久久中文字幕 | 久草成人在线 | 精品久久久久久亚洲精品 | 国产成人aⅴ | 精国产品一区二区三区 | 日韩精品一区二 | 一区二区久久久久草草 | 日本教室三级在线看 | 久久久久久久久久亚洲 | 在线成人www免费观看视频 | 国产污污视频 | 欧美精品123区 | 99视频网址 | 麻豆911 | 久久精品国产99久久久古代 | 国产免费看片 | 99精品视频免费看 | 亚洲欧美国产高清 | 国产免费久久久久 | 桥本有菜免费av一区二区三区 | www.成人在线视频 | 毛片免费一区二区三区 | 美国一级毛片片aa久久综合 | 国产欧美在线观看不卡一 | av电影网站在线观看 | 国产a级片电影 | 极品xxxx欧美一区二区 | 免费在线观看成人av | 欧美成人精品一级 | 国产一级毛片高清视频完整版 | 国产精品一区免费在线观看 |