> Using C to implement WebService, gsoap is the best choice. . I 've been tossing this for nearly a month. Let's make a conclusion. It may take a long time to write it. This is because many problems have been encountered, but the adjustments have finally been solved.
> Quick Start
1. gsoap official website. When you encounter problems, the official website is often the most helpful place.
Http://gsoap2.sourceforge.net/
2. Several references.
Gsoap experience: http://www.cppblog.com/qiujian5628/archive/2008/10/11/54019.html
Gsoap Interface Definition: http://blog.sina.com.cn/s/blog_5ee9235c0100de3g.html
> TestCode .
I developed it in C in Linux. Let's start with makefile. For the server-side code and client-side code, refer to gsoap experiences or examples provided by gsoap.
A. Use soapcpp2 to produce gsoap-related code: $ (gsoap_bin)/soapcpp2-C-x $ {wsname}. h
B. The Code required by the server: soapc. c soapserver. c stdsoap2.c
C. Code required by the Client: soapc. c soapclient. c stdsoap2.c
D. stdsoap2.c is copied from the gsoap development kit, and its file is generated by the command in (.
------------- Separator ------------------------------------
Gsoap_bin =/usr/local/gsoap/bin
Wsname0 = soap
Wsname = smswbs
Server_objs = $ (wsname0) c. o $ (wsname0) server. O stdsoap2.o $ {wsname} server. o
Client_objs = $ (wsname0) c. o $ (wsname0) client. O stdsoap2.o $ {wsname} client. o
Aa_objs = $ (wsname0) c. o $ (wsname0) server. o $ (wsname0) client. O stdsoap2.o $ {wsname} server. o $ {wsname} client. o
Include =
Libs =
Cc = g ++-g-dwith_nonamespaces
# Libs =-LZ-LC-lncurses-lssl-lcrypto
# Cc = g ++-g-dwith_nonamespaces-dwith_openssl
ALL: Server
ALL: Client
$ {Wsname}. WSDL: $ {wsname}. h
$ (Gsoap_bin)/soapcpp2-C-x $ {wsname}. h
$ (Aa_objs): %. O: %. c
$ (CC)-C $? $ (Include)
Server: makefile $ {wsname}. WSDL $ (server_objs)
$ (CC) $ (server_objs) $ (libs)-O smsserver-lpthread
Client: makefile $ {wsname}. WSDL $ (client_objs)
$ (CC) $ (client_objs) $ (libs)-O smsclient
Clean:
Rm-f *. O *. xml *. A *. WSDL *. nsmap \
$ (Wsname0) h.h $ (wsname0) C. C $ (wsname0) server. C $ (wsname0) client. c \
$ (Wsname0) Stub. * $ (wsname) proxy. * $ (wsname) object .*\
$ (Wsname0) serverlib. C $ (wsname0) clientlib. C $ (wsname) server ns. XSD $ (wsname) test
Clear:
Rm-f *. o ns. XSD
------------- Separator ------------------------------------
> Interface Definition For more information, see gsoap interface definition. Here I will provide the interface form for C # To reference this webserver.
Gsoap is based on the. h file we have defined, and then generates the. c file we need using tools. Therefore, we must write. h according to the requirements of gsoap.
1. output of a single parameter:
Int NS _ add (int A, int B, int * C );
Note that the NS _ here is mandatory and must begin with the NS in the Start comment with two underscores. The return value must be Int.
But the int here is not the return value of the interface, but the return value inside gsoap. The true return value is int * C.
The corresponding interface in C #: int add (int A, int B); the return value is the preceding int * C parameter.
2. Multiple parameters are transferred out. The struct must be used in the interface.
Typedef char * XSD _ string;
Typedef long XSD _ int;
Struct NS _ personresponse {
XSD _ int age;
XSD _ string name;
XSD _ string address;
};
Int NS _ person (XSD _ string buf_in, struct NS _ personresponse * buf_out );
In C #, this is not what we declare. Int person (string buf_in, out string name, out string address );
That is, the first field in the struct changes to the return value, and the others change to output parameters one by one.
3. Return struct. If you want to return the structure chart, you must set another struct In the struct:
Typedef char * XSD _ string;
Typedef long XSD _ int;
Struct NS _ person {
XSD _ int age;
XSD _ string name;
XSD _ string address;
};
Struct NS _ personresponse {
XSD _ int ret;
Struct NS _ person;
};
Int NS _ person (XSD _ string buf_in, struct NS _ personresponse * buf_out );
In C #, the interface is as follows: int person (string buf_in, the structure class of person );
4. The underline in the interface. If the transaction name in the interface is underlined, it must be declared as follows:
Int NS _ echo_uscorereverse (char * buf_in, char ** buf_out );
In C #, the actual interface name is: String echo_reverse (string buf_in );
string returned in gsoap
1. The following is a function to reverse the string.
int NS _ echo_uscorereverse (char * buf_in, char ** buf_out);
int NS _ echo_uscorereverse (struct soap * add_soap, char * buf_in, char ** buf_out)
{< br> int I, j, Len;
printf ("ns _ interface: In = [% s] \ n ", buf_in);
Len = strlen (buf_in);
* buf_out = (char *) soap_malloc (add_soap, Len + 1 );
for (I = len-1, j = 0; I> = 0; I --, J ++) {
(* buf_out) [J] = buf_in [I];
}< br> (* buf_out) [J] = 0;
Return 0;
}
Call soap_malloc to apply for a space and assign it to the return parameter buf_out. This space will be released when soap_end is called.
> Gsoap transmits Chinese Characters . I use UTF-8 encoding to support Chinese Character transmission.
1. Set gsoap to UTF-8 for data transmission
Soap_set_mode (& smswbs_soap, soap_c_utfstring); // sets the Encoding
Smswbs_soap.mode | = soap_c_utfstring;
2. Use the following function to convert our transmitted content to convert our data into UTF-8 encoding:
Int conv_charset (const char * DEST, const char * SRC, char * input, size_t ilen, char * output, size_t olen)
{
Int convlen = olen;
Iconv_t Conv = iconv_open (DEST, Src );
If (Conv = (iconv_t)-1)
Return-1;
Memset (output, 0, olen );
If (iconv (Conv, & input, & ilen, & output, & olen )){
Iconv_close (Conv );
Return-1;
}
Iconv_close (Conv );
Return convlen-olen;
}
Example: conv_charset ("UTF-8", "GBK", "Lin Xue Ren. linxr", strlen ("Lin Xue Ren. linxr"), buf_out-> name, 100 );
> Webserver released
1. in C #, you can directly reference a webserver. But how can we use webserver to reference it. In fact, you only need to implement the fget callback function of gsoap:
Smswbs_soap.fget = http_get;
2. Implement the http_get Function
Int http_get (struct soap * soap)
{
File * FD = NULL;
Char * s = strchr (soap-> path ,'? ');
If (! S | strcmp (S ,"? WSDL ")){
Return soap_get_method;
}
FD = fopen ("smswbs. WSDL", "rb ");
If (! FD ){
Return 404;
}
Soap-> http_content = "text/XML ";
Soap_response (soap, soap_file );
For (;;){
Size_t r = fread (soap-> tmpbuf, 1, sizeof (soap-> tmpbuf), FD );
If (! R ){
Break;
}
If (soap_send_raw (soap, soap-> tmpbuf, R )){
Break;
}
}
Fclose (FD );
Soap_end_send (SOAP );
Return soap_ OK;
}