본문 바로가기

MS/C++

gsoap

출처 : http://blog.naver.com/hwmin75?Redirect=Log&logNo=50095054999
일단 인덱싱 해놓고 슬슬 봐야겠습니다.

HOW TO gsoap

Install

http://gsoap2.sourceforge.net/에서 최신 soap(현재는 2.7이다)를 다운받는다.

설치는 유분투 리눅스를 기준으로 한다.

  1. 압축을 푼다.
  2. openssl 라이브러리가 없는 관계로 아래와 같이 설치 한다. 자세한 내용은 readme을 참조한다.

To build without OpenSSL support, use:

$ ./configure --disable-openssl

$ make

$ make install

위과정으로 모든 설치가 끝났다.

결국 여기서 주목해야 되는 결과물은 wsdl2h, soapccp2 이다.

wsdl2h

WSDL 문서를 gSOAP header 파일로 변경한다.

예) wsdl2h –c infile.wsdl –o infile.h

로컬 컴퓨터 내부에 있는 WSDL파일을 사용할수도 있지만 URL 형식으로 인터넷상의 WSDL 파일을 사용할수도 있다.

soapcpp2

wsdl2h로 생성된 header file을 사용하여 stub code를 생성한다

soapcpp2 -c -I/usr/local/share/gsoap/import calc.h

여기서 –I/ 이후 import로 가는 패스를 정확히 지정해 주어야 나중에 에러가 발생하지 않는다.

어떤 문헌에는 –i/usr/share/gsoap/imprt로 표시되어 있다.

-c는 c언어 형태의 스텁 코드를 생성하라는 의미이다.

결과는 다음과 같고, 서버와 클라이언트 관련 코드들과 예제 XML파일들이 생성된다.

calc.h 파일을 바탕으로 [soapcpp2]가 위와 같은 파일들을 자동으로 만들어 줍니다. 이 파일들은 서버의 구성 및 네트워크 통신에 대한 모든 부분을 처리해 줍니다. [calc.add.req.xml] 과 [calc.add.res.xml] 은 SOAP 통신시 서버와 클라이언트간의 주고 받는 xml의 내용들입니다. 한번쯤은 파일을 열어서 SOAP에서의 xml 데이터 형식이 어떤지 보는게 좋을거 같습니다. 나머지들은 한번쯤 봐도 좋지만 조금 복잡한 구조로 되어있으니 그냥 우린 서비스에만 촞점을 맞춰서 그냥 넘어가겠습니다.( namomo.egloos.com/3277284에서 참고)

client 코드 작성하기

아래의 코드를 client.c로 작성하고 저장한다.

(아래코드는 gsoap 매뉴얼 7.1에서 참고한 코드를 약간수정한 것이다.)

클라언트를 컴파일하기 위해서는 stdsoap2.c/h를 gsoap 쏘스 파일에서 작업 디렉토리로 복사해야한다.

다음과 같이 컴파일을 하고 결과를 확인한다.

위의 클라이언트는 디폴트로 http://websrv.cs.fsu.edu/~engelen/calcserver.cgi에 연결된 cgi 서버에서 결과를 가져온다.

server 코드 작성하기

soapcpp2을 통해서 생성된 파일들에는 stub code만 있으므로 실제 프로그램이 동작을 하기위해서는 main function과 각 API들의 내용이 구현되어야 한다. 구현되어야 main코드는 soapStub.h에 다음과 같이 선언되어 있따.

SOAP_FMAC5 int SOAP_FMAC6 ns2__add(struct soap*, double a, double b, double *result);

SOAP_FMAC5 int SOAP_FMAC6 ns2__sub(struct soap*, double a, double b, double *result);

SOAP_FMAC5 int SOAP_FMAC6 ns2__mul(struct soap*, double a, double b, double *result);

SOAP_FMAC5 int SOAP_FMAC6 ns2__div(struct soap*, double a, double b, double *result);

SOAP_FMAC5 int SOAP_FMAC6 ns2__pow(struct soap*, double a, double b, double *result);

calcServer.c

#include <math.h>

#include "calc.nsmap"

SOAP_FMAC5 int SOAP_FMAC6 ns2__add(struct soap *soap, double a, double b, double *result)

{

printf("[Add] %.3f + %.3f \n", a, b);

*result = a + b;

return SOAP_OK;

}

int ns2__sub(struct soap *soap, double a, double b, double *result)

{

*result = a - b;

return SOAP_OK;

}

int ns2__mul(struct soap *soap,double a, double b, double *result)

{

*result = a*b;

return SOAP_OK;

}

int ns2__div(struct soap *soap,double a, double b, double *result)

{

*result = a/b;

return SOAP_OK;

}

int ns2__pow(struct soap *soap,double a, double b, double *result)

{

*result = pow(a, b);

return SOAP_OK;

}

int main(int argc, char **argv)

{

int m, s; /* master and slave sockets */

struct soap soap;

soap_init(&soap);

if (argc < 2) {

soap_serve(&soap); /* serve as CGI application */

} else {

m = soap_bind(&soap, NULL, atoi(argv[1]), 100);

if (m < 0) {

soap_print_fault(&soap, stderr);

exit(-1);

}

fprintf(stderr, "Socket connection successful: master socket = %d\n", m);

for ( ; ; ) {

s = soap_accept(&soap);

fprintf(stderr, "Socket connection successful: slave socket = %d\n", s);

if (s < 0) {

soap_print_fault(&soap, stderr);

exit(-1);

}

soap_serve(&soap);

soap_end(&soap);

}

}

return 0;

}

컴파일은 다음과 같다.

gcc -o server calcServer.c soapC.c soapServer.c stdsoap2.c -lm

server 실행파일은 두가지 타입의 서버를 지원한다.

server실행시 인자가 없는 경우는 CGI Type 서버가 되서 웹서버의 cgi-bin 디렉토리에 copy하고 client에서 아래의 URL로 접근하여 API를 호출 할 수 있다고 한다. client 코드 작성하기에서 이런 형태의 서버를 사용했다.

이것을 Test할수 있는 또 다른방법은 아래와 같다.

namomo.egloos.com/3283496에서 발췌한 내용임.

우선 실행하기 이전에 자동 생성된 xml을 이용해서 서버가 정상적으로 서비스가 가능한지 확인합니다. 서버에 request 값을 보내서 어떤 값을 받을 수 있는지 확인해 봅시다. calc.add.req.xml 파일을 열어보면 아래와 같습니다.

calc.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="ns">

<SOAP-ENV:Body>

<ns:add>

<a>0.0</a>

<b>0.0</b>

</ns:add>

</SOAP-ENV:Body>

</SOAP-ENV:Envelope>

<ns:add>를 보면 우리가 사용할 서비스가 add 라는 것을 알 수 있습니다.

이 add에는 a와 b값을 넣어서 보내면 된다는 것도 알 수 있고요.

a와 b값을 각각 3.0 4.5 를 넣어 봅시다.

그리고 파일을 저장하고 서버에 위의 xml 파일을 보내보죠.

실행은 아래와 같습니다.

./server < calc.add.req.xml

결과를 보면 아래와 같은 내용을 보여줍니다.

[Add] 3.000 + 4.500

Status: 200 OK

Server: gSOAP/2.7

Content-Type: text/xml; charset=utf-8

Content-Length: 393

Connection: close

<?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="ns">

<SOAP-ENV:Body>

<ns:addResponse>

<result>7.5</result>

</ns:addResponse>

</SOAP-ENV:Body>

</SOAP-ENV:Envelope>

두번째 타입의 서버는 standalone 타입이다.

다음과 같이 실행하면 된다. ./server 8888 &

서버가 정상적으로 동작하는지를 test하기 위해서는 또 다시 클라이언트 프로그램이 필요한다. 이 프로그램은 다음과 같다.

#include "soapH.h"

#include "calc.nsmap"

int main()

{

double result = 0.0f, a = 0.0f, b = 0.0f;

struct soap soap;

soap_init(&soap);

a = 10.0f;

b = 5.0f;

if(soap_call_ns2__add(&soap, http://localhost:8888,NULL, a, b, &result) == SOAP_OK)

{

fprintf(stderr, "%0.2f + %0.2f = %0.2f\n", a, b, result);

}

else

{

fprintf(stderr, "Add request failed\n");

soap_print_fault(&soap, stderr);

}

soap_destroy(&soap);

soap_end(&soap);

soap_done(&soap);

return 0;

}

test 결과는

참고자료 : http://kylesoft.springnote.com/pages/5553901를 많이 참조했다.

[출처] HOW TO gsoap|작성자 민이라구