SOAP 라이브러리 기술조사에 이어 gSOAP 라이브러리를 사용하는데 필요한 내용을 정리해 보았습니다.
사용자는 gSOAP 라이브러리에서 제공하는 다음 두가지 명령을 사용하여 클라이언트/서버 코드를 생성합니다.
wsdl2h
- C와 C++을 위한 WSDL 파서 입니다. 이 명령을 통해 gSOAP이 스텁(stub) 코드와 스켈레톤(skeleton) 코드를 생성하는데 바탕이 되는 헤더 파일을 생성합니다.
soapcpp2
wsdl2h로 만든 헤더 파일을 기반으로 C와 C++을 위한 스텁 코드와 스켈레톤 코드를 생성합니다.soapH.hsoapC.c: 데이터 자료형을 위한 XML 시리얼라이저 (serializer) 입니다. 즉, XML 스키마 상의 anyURI, token 과 같은 자료형을 그와 매칭되는 C/C++ 자료형으로 변환하고, 처리합니다.soapClient.c: 클라이언트 측 스텁 코드 입니다. 클라이언트 서비스 함수를 호출하기만 하면 됩니다.soapServer.c: 서버 측 스켈레톤 코드 입니다. 서버는 서비스 함수를 구현해야 합니다.typemap.dat: 사용자가 네임스페이스의 어미(prefix)를 지정하거나 자료형 맵핑을 변경할 수 있습니다.[service_name].nsmap: 해당 서비스에서 사용하는 실제적인 네임스페이스 정의(코드) 입니다.
메모리 관리
gSOAP을 이용하여 서버/클라이언트를 작성할 때, 사용자는 클라이언트 요청, 서버 응답에 해당하는 파라미터에 값을 넣어주게 됩니다. 이 때, 메모리 할당이 필요할 경우 gSOAP에서 제공하는 메모리 할당 API를 사용하면, soap 서비스를 종료할 때, 정확히는 soap_end()를 호출 할 때, 자동으로 할당한 메모리를 해제해 줍니다.
- soap_malloc () : malloc()에 대한 gSOAP 렙퍼 함수
- soap_strdup () : strdup()에 대한 gSOAP렙퍼 함수
- soap_dealloc () : 동적으로 할당한 메모리 해제
서버 동작
기본적으로 gSOAP은 비동기 방식을 지원하지 않는다고 합니다. 따라서 서비스를 제공하기 위해서 주로 쓰레드를 사용하는 것 같습니다.
서버의 기본 동작은 다음과 같을 것입니다.
서버 (기본 프로세스/쓰레드)
- soap_new () : soap 객체 생성
- soap_bind () : bind 랩퍼 함수
- soap_accept() : accept 랩퍼 함수
- soap_copy () : soap 문맥 복사
서버 (실제 서비스를 제공하는 쓰레드)
- soap_serve() : 최종적으로 사용자가 작성한 서비스를 호출합니다.
- soap_destroy () : C++ 객체와 관련된 동적 메모리 해제
- soap_end () : 임시 데이터 등 메모리 해제
- soap_free() : soap 객체 해제
서버는 soapStub.h 파일에서 Service Operation 에 해당하는 함수(서비스)를 구현하면 되고, 클라이언트는 soapStub.h 파일에서 주석으로 Stubs 라고 명시된 부분의 함수를 이용하여 서비스를 이용하면 됩니다. 다음은 간단한 서버 예제입니다.
int
main(int argc, char **argv)
{
struct soap soap, *tsoap;
pthread_t tid;
int m, s;
soap_init2 (&soap, SOAP_IO_KEEPALIVE, SOAP_IO_KEEPALIVE);
soap.max_keep_alive = 100;
soap.accept_timeout = 600;
m = soap_bind (&soap, NULL, 18000, BACKLOG);
if (m < 0)
{
soap_print_fault (&soap, stderr);
exit (1);
}
fprintf(stderr, "Socket connection successful %d\n", m);
for (count = 0; count & gt; = 0; count++)
{
soap.socket_flags = MSG_NOSIGNAL;
soap.accept_flags = SO_NOSIGPIPE;
s = soap_accept (&soap);
if (s < 0)
{
if (soap.errnum)
soap_print_fault (&soap, stderr);
else
fprintf (stderr, "Server timed out\n");
break;
}
fprintf (stderr, "Accepts socket %d connection from IP %d.%d.%d.%d\n",
s,
(int)(soap.ip >> 24)&0xFF,
(int)(soap.ip >> 16)&0xFF,
(int)(soap.ip >> 8)&0xFF,
(int)soap.ip&0xFF);
tsoap = soap_copy (&soap);
pthread_create (&tid,
NULL,
(void *(*)(void *)) process_request,
(void *) tsoap);
}
return 0;
}
void *
process_request(void *soap)
{
pthread_detach (pthread_self ());
((struct soap*) soap)->recv_timeout = 300;
((struct soap*) soap)->send_timeout = 60;
soap_serve ((struct soap*) soap);
soap_destroy ((struct soap*) soap);
soap_end ((struct soap*) soap);
soap_free ((struct soap*) soap);
return NULL;
}

This work, unless otherwise expressly stated, is licensed under a Creative Commons Attribution-Noncommercial-No Derivative Works 2.0 Korea License.