gsop를 통해 https 기반 웹 서비스 인터페이스를 호출하는 C++ 요약

와우 단계:

1단계: 헤더 파일 생성

웹서비스 인터페이스에는 일반적으로 외부 인터페이스 문서가 있습니다. 예: http://www.webxml.com.cn/WebServices/WeatherWebService.asmx?WSDL

물음표 뒤의 매개변수는 XML 문서인 WSDL 문서를 의미하며, 구성을 이해하지 못해도 상관없으며, 다음으로 이 문서를 통해 C++ 헤더 파일을 생성해야 합니다.

(1) gsoap 도구 다운로드

다운로드 링크: gSOAP 툴킷 다운로드 | SourceForge.net

 다운로드가 완료되면 압축을 풀고 gsoap\bin\win32 디렉터리로 들어갑니다. 이 디렉터리에는 wsdl2h.exe와 Soapcpp2.exe라는 두 개의 파일이 있습니다. wsdl2h.exe는 헤더 파일을 생성하는 데 사용됩니다. 헤더 파일 생성만으로는 충분하지 않으며, 이때 비누cpp2.exe를 이용하여 해당 C++ 파일 구조를 생성해야 하며, 이는 프로젝트에서 호출할 때 사용할 수 있습니다(두 번째 단계에서 소개). 먼저 헤더 파일을 생성하는 방법을 살펴보겠습니다.

 gsoap\bin\win32 디렉터리에서 cmd 명령을 엽니다. 입력하다:

wsdl2h.exe -o head.h http://www.webxml.com.cn/WebServices/WeatherWebService.asmx?WSDL

 실행이 완료되면 현재 디렉터리에 추가 헤더 파일 head.h가 있는 것을 확인할 수 있습니다. 열어서 살펴볼 수 있으며 내부에는 몇 가지 인터페이스 기능이 있습니다.

 참고: 웹 서비스는 전송 프로세스 중에 기본적으로 UTF-8 인코딩을 사용합니다. 물론 gsoap도 헤더 ​​파일을 생성할 때 기본적으로 좁은 문자를 사용합니다. 문자열 또는 char* 등. 이때, 다시 호출 시 매개변수에 한자가 포함되어 있으면 문자가 깨져서 나옵니다. 두 가지 해결책이 있습니다.

방법 1: 나중에 호출할 때 코드에 문장을 추가합니다. (구체적으로 추가할 위치는 나중에 소개하겠습니다.)

soap_set_mode(&m_soap, SOAP_C_UTFSTRING);

 방법 2: 기본적으로 루트 디렉터리에 있는 typemap.dat를 사용하여 좁은 문자로 컴파일합니다. 지금은 적용하지 않고 현재 디렉터리에 새로운 mytypemap.dat를 생성합니다. 내용은 다음과 같습니다: xsd__string = | std::wstring | wchar_t*. 그런 다음 cmd 명령을 다시 실행하십시오.

wdsl2h.exe -o head.h -t mytypemap.dat http://www.webxml.com.cn/WebServices/WeatherWebService.asmx?WSDL

 재생성 후 head.h의 문자열 유형이 wchar_t * 또는 wstring 유형으로 변경된 것을 확인할 수 있습니다.

2단계: 호출 가능한 API 생성

현재 디렉터리에서 cmd 명령을 실행합니다.

soapcpp2.exe -C -x -I ..\..\import head.h

  

그 중 -C는 클라이언트 코드만 생성합니다. -x는 xml을 생성하지 않음을 의미합니다(C++ 코드만 필요함). -I는 가져오기 디렉터리를 지정한다는 의미입니다.
성공적으로 실행되면 현재 디렉터리에 몇 가지 파일이 더 남게 됩니다.

 3단계: 프로젝트로 가져오기
위 그림의 빨간색 상자에 있는 파일을 프로젝트에 추가합니다. 추가해야 할 파일이 두 개 더 있습니다. gsoap 루트 디렉터리의 stdsoap2.h 및 stdsoap2.cpp도 프로젝트에 추가해야 합니다.
추가된 세 개의 cpp 파일->속성->모든 구성->c/c+±>미리 컴파일된 헤더를 마우스 오른쪽 버튼으로 클릭하고 미리 컴파일된 헤더를 사용하지 않도록 선택합니다. 아래 그림과 같이.

구성이 완료되면 코드 작성을 시작할 수 있습니다.

4단계: 코드 작성

SoapTest라는 새 MFC 기반 애플리케이션 프로젝트를 만듭니다. 

새로운 SoapTestDlg.cpp를 생성하고 헤더 파일을 소개합니다.

#include "WeatherWebServiceSoap.nsmap"
#include "soap.h"

프로젝트에서 이 두 헤더 파일을 참조했을 때 컴파일 시 엄청난 오류가 보고되었습니다. 자세히 확인해보니 모두 중복된 정의였습니다. 이유는 헤더 파일 WeatherWebServiceSoap.nsmap 의 네임스페이스가 프로젝트의 원본 소켓 라이브러리와 충돌하기 때문입니다. 해결 방법은 앞에 #include "WeatherWebServiceSoap.nsmap"을 쓰는 것입니다. .미리 컴파일된 헤더를 사용하는 경우 stdafx.h 파일에 작성하는 것이 가장 좋습니다. 헤더 파일이 도입된 후 다시 컴파일하면 오류가 보고되지 않습니다. 미리 컴파일된 헤더를 추가하지 않는 경우 미리 컴파일된 헤더를 사용하지 않도록 비누C.cpp, 비누클라이언트Lib.cpp, 비누클라이언트.cpp, stdsoap2.cpp를 설정해야 합니다.


서비스의 모든 인터페이스는 SoapClient.cpp에서 볼 수 있습니다. 함수 이름은 Soap_call __ns1_XXX 형식입니다.
먼저 비누 객체를 생성하고 초기화합니다.

struct soap m_soap;
//SOAP初始化
soap_init(&m_soap);
soap_set_mode(&m_oSoap, SOAP_C_UTFSTRING);

soap_set_mode(&m_oSoap, SOAP_C_UTFSTRING);한자에 적응하기 위해 처음에 말한 것이 바로 그것 입니다. 처음에 wstring이나 wchar_t *를 사용했다면 무시해도 됩니다. 그런 다음 reqXml 문자열을 정의하고 인터페이스 함수를 호출합니다. XML 문자열의 큰따옴표를 이스케이프해야 합니다.

char* _reqXml = "<root>.....</root>";
char* _Return;
soap_call_ns1__XXX(&m_soap, NULL, NULL, G2U(_reqXml), _Return);
string ret = U2G(_Return);

위 코드는 매개변수로 좁은 문자, 즉 char *를 사용하므로 UTF-8 형식으로 변환해야 합니다. 구체적인 기능은 다음과 같습니다.

char* U2G(const char* utf8)
{
	int len = MultiByteToWideChar(CP_UTF8, 0, utf8, -1, NULL, 0);
	wchar_t* wstr = new wchar_t[len + 1];
	memset(wstr, 0, len + 1);
	MultiByteToWideChar(CP_UTF8, 0, utf8, -1, wstr, len);
	len = WideCharToMultiByte(CP_ACP, 0, wstr, -1, NULL, 0, NULL, NULL);
	char* str = new char[len + 1];
	memset(str, 0, len + 1);
	WideCharToMultiByte(CP_ACP, 0, wstr, -1, str, len, NULL, NULL);
	if (wstr) delete[] wstr;
	return str;
}

char* G2U(const char* gb2312)
{
	int len = MultiByteToWideChar(CP_ACP, 0, gb2312, -1, NULL, 0);
	wchar_t* wstr = new wchar_t[len + 1];
	memset(wstr, 0, len + 1);
	MultiByteToWideChar(CP_ACP, 0, gb2312, -1, wstr, len);
	len = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, NULL, 0, NULL, NULL);
	char* str = new char[len + 1];
	memset(str, 0, len + 1);
	WideCharToMultiByte(CP_UTF8, 0, wstr, -1, str, len, NULL, NULL);
	if (wstr) delete[] wstr;
	return str;
}

이 시점에서 컴파일이 통과되어야 합니다. 그러나 현실은 잔인하다. 반환된 _Return 값은 NULL이며, 이는 문제가 발생했음을 나타냅니다. 제 주소는 https입니다. http로 직접 요청하면 301이 나오네요. 검색정보에는 301이 리다이렉션을 의미한다고 되어 있는데, 이는 브라우저처럼 주소창에 http를 입력할 수 없고, 브라우저가 https로 리다이렉트한다는 뜻입니다. . 이때는 여전히 https로 변경해야 합니다. 다시 컴파일하십시오. 음~ 아직도 오류를 보고하고 있어요. . . 에러코드는 디버깅 중 m_soap 구조체의 error 필드 값을 확인할 수 있는데, 항상 0이면 문제가 없다는 뜻이다. 특정 오류 코드는 온라인으로 확인할 수 있습니다.
https로 변경 후 디버깅을 해보면 m_soap->error 값이 30인 것을 확인할 수 있습니다. 설명서를 확인해보니 30은 SSL 보안 인증을 수행하지 않는다는 의미라는 것을 알 수 있습니다. 좋아요 ~
soap_init(&m_soap) 뒤에 다음 코드를 추가하세요.

soap_ssl_init();
if (soap_ssl_server_context(&m_soap, SOAP_SSL_NO_AUTHENTICATION, NULL, NULL, NULL, NULL, NULL, NULL, NULL)) {
	soap_print_fault(&m_soap, stderr);
	exit(-1);
}

Soap_ssl_server_context 매개변수에 SSL 인증서가 있는 경우 비밀번호를 입력하세요. 모두 NULL이 아니어도 괜찮습니다.
다시 컴파일한 후에도 ~를 통해 코드를 확인할 수 없었고 stdsoap2.h헤더 파일 에 WITH_OPENSSL이 정의되어 있지 않은 것을 발견했습니다 . 아래는 회색입니다.

 해결 방법: 프로젝트 속성을 마우스 오른쪽 버튼으로 클릭하고 -> C/C+±> 전처리기 -> 전처리기 정의에서 WITH_OPENSSL 추가를 클릭합니다.

 추가하고 보니 회색빛이 사라졌네요.

 컴파일 후 오류가 다시 보고됩니다. 오류 메시지는 soap_ssl_server_context함수로 해결할 수 없는 외부 기호입니다.

이유

        이 함수의 구현은 정의되지 않았습니다. openssl 라이브러리를 소개하는 것을 잊었습니다. 다운로드 주소: https://slproweb.com/products/Win32OpenSSL.html

다운로드 완료, 설치, 설치 완료 디렉터리입니다.

 그런 다음 vs->속성->구성 속성->아래 표시된 대로 VC++ 디렉터리에 포함 디렉터리와 라이브러리 디렉터리를 추가에서 프로젝트를 마우스 오른쪽 버튼으로 클릭합니다.

 아래와 같이 vs->속성->구성 속성->라이브러리 연결->입력->추가 종속 라이브러리 항목에 libcrypto.lib 및 libssl.lib 추가에서 프로젝트를 마우스 오른쪽 버튼으로 클릭합니다.

파일 구조

 알아채다:

아래와 같이 비누클라이언트.obj에 xx가 정의되어 있다는 오류가 보고되는 경우

 해결책:

        모든 SoapClientLib.cpp를 주석 처리하고 다시 컴파일하십시오.

 다음은 gsoap+opensll 도구입니다.

https://download.csdn.net/download/my_angle2016/88220982

추천

출처blog.csdn.net/my_angle2016/article/details/132302759