客户端必须准备好有效载荷,将其发送到服务,然后接收并处理从服务端发来的响应。
客户端代码示例:
#include <stdio.h> #include <axiom.h> #include <axis2_util.h> #include <axiom_soap.h> #include <axis2_client.h> axiom_node_t * build_om_request(const axutil_env_t *env); const axis2_char_t * process_om_response(const axutil_env_t *env, axiom_node_t *node); int main(int argc, char** argv) { const axutil_env_t *env = NULL; const axis2_char_t *address = NULL; axis2_endpoint_ref_t* endpoint_ref = NULL; axis2_options_t *options = NULL; const axis2_char_t *client_home = NULL; axis2_svc_client_t* svc_client = NULL; axiom_node_t *payload = NULL; axiom_node_t *ret_node = NULL; env = axutil_env_create_all("hello_client.log", AXIS2_LOG_LEVEL_TRACE); options = axis2_options_create(env); address = "http://localhost:9090/axis2/services/hello"; if (argc > 1) address = argv[1]; if (axutil_strcmp(address, "-h") == 0) { printf("Usage : %s [endpoint_url]\n", argv[0]); printf("use -h for help\n"); return 0; } printf("Using endpoint : %s\n", address); endpoint_ref = axis2_endpoint_ref_create(env, address); axis2_options_set_to(options, env, endpoint_ref); client_home = AXIS2_GETENV("AXIS2C_HOME"); if (!client_home && !strcmp(client_home, "")) client_home = "../.."; svc_client = axis2_svc_client_create(env, client_home); if (!svc_client) { printf("Error creating service client\n"); AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Stub invoke FAILED: Error code:" " %d :: %s", env->error->error_number, AXIS2_ERROR_GET_MESSAGE(env->error)); return -1; } axis2_svc_client_set_options(svc_client, env, options); payload = build_om_request(env); ret_node = axis2_svc_client_send_receive(svc_client, env, payload); if (ret_node) { const axis2_char_t *greeting = process_om_response(env, ret_node); if (greeting) printf("\nReceived greeting: \"%s\" from service\n", greeting); axiom_node_free_tree(ret_node, env); ret_node = NULL; } else { AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Stub invoke FAILED: Error code:" " %d :: %s", env->error->error_number, AXIS2_ERROR_GET_MESSAGE(env->error)); printf("hello client invoke FAILED!\n"); } if (svc_client) { axis2_svc_client_free(svc_client, env); svc_client = NULL; } if (env) { axutil_env_free((axutil_env_t *) env); env = NULL; } return 0; } axiom_node_t * build_om_request(const axutil_env_t *env) { axiom_node_t* greet_om_node = NULL; axiom_element_t * greet_om_ele = NULL; greet_om_ele = axiom_element_create(env, NULL, "greet", NULL, &greet_om_node); axiom_element_set_text(greet_om_ele, env, "Hello Server!", greet_om_node); return greet_om_node; } const axis2_char_t * process_om_response(const axutil_env_t *env, axiom_node_t *node) { axiom_node_t *service_greeting_node = NULL; axiom_node_t *return_node = NULL; if (node) { service_greeting_node = axiom_node_get_first_child(node, env); if (service_greeting_node && axiom_node_get_node_type(service_greeting_node, env) == AXIOM_TEXT) { axiom_text_t *greeting = (axiom_text_t *)axiom_node_get_data_element(service_greeting_node, env); if (greeting && axiom_text_get_value(greeting , env)) { return axiom_text_get_value(greeting, env); } } } return NULL; }
使用Axis2/C实现客户端时遵循的步骤:
- 创建客户端使用的环境
Axis2/C的每个函数都需要一个只想环境实例的指针,该实例封装了内存分配器,错误处理程序及日志和线程机制。axutil_env_create_all函数可用于创建默认的,准备使用的环境实例。
axutil_env_create_all声明如下:axutil_env_t *axutil_env_create_all(const axis2_char_t * log_file, const axutil_log_levels_t log_level);
使用示例:const axutil_env_t *env = NULL; env = axutil_env_create_all("hello_client.log", AXIS2_LOG_LEVEL_TRACE);
- 创建一个选项实例,并设置选项
axis2_options结构可用于设置客户端选项。例如,可使用options设置客户端所使用的服务终端地址。示例:options = axis2_options_create(env); const axis2_char_t *address = NULL; address = "http://localhost:9090/axis2/services/hello"; axis2_endpoint_ref_t* endpoint_ref = NULL; endpoint_ref = axis2_endpoint_ref_create(env, address); axis2_options_set_to(options, env, endpoint_ref);
- 创建服务客户端实例,并将客户端仓库文件夹路径作为参数传递给实例。
axis2_svc_client结构被用于用户使用Web服务,它提供了一个易于使用的API。服务客户端axis2_svc_client_create函数将仓库地址作为参数。本例中,使用AXIS2C_HOME作为仓库地址。示例:axis2_svc_client_t* svc_client = NULL; const axis2_char_t *client_home = NULL; client_home = AXIS2_GETENV("AXIS2C_HOME"); svc_client = axis2_svc_client_create(env, client_home);
- 对服务客户端实例设置选项
在前步中创建的options必须在服务客户端上进行设置,指示服务客户端上可使用的选项。示例:axis2_svc_client_set_options(svc_client, env, options);
- 发送请求并接收响应
服务客户端的axis2_svc_client_send_receive函数用于调用服务客户端实例的发送接收操作。发送接收操作将请求有效载荷作为axiom_node并将响应有效载荷作为axiom_node返回,一旦接收到响应,响应有效载荷将被存储在axiom_node指针(本例为ret_node)中,该指针可用于进一步处理响应。示例:axiom_node_t *payload = NULL; axiom_node_t *ret_node = NULL; payload = build_om_request(env); ret_node = axis2_svc_client_send_receive(svc_client, env, payload); axiom_node_t * build_om_request(const axutil_env_t *env) { axiom_node_t* greet_om_node = NULL; axiom_element_t * greet_om_ele = NULL; greet_om_ele = axiom_element_create(env, NULL, "greet", NULL, &greet_om_node); axiom_element_set_text(greet_om_ele, env, "Hello Server!", greet_om_node); return greet_om_node; }
- 处理响应
根据业务逻辑处理响应。示例:const axis2_char_t *greeting = process_om_response(env, ret_node); if (greeting) printf("\nReceived greeting: \"%s\" from service\n", greeting); axiom_node_free_tree(ret_node, env); ret_node = NULL;
编译客户端
Linux:
gcc -o hello -I$AXIS2C_HOME/include/axis2-1.6.0/ -L$AXIS2C_HOME/lib -laxutil -laxis2_axiom -laxis2_parser -laxis2_engine -lpthread -laxis2_http_sender -laxis2_http_receiver hello.c -ldl -Wl,--rpath -Wl,$AXIS2C_HOME/lib
MS Windows:
编译:
cl.exe /nologo /D "WIN32" /D "_WINDOWS" /D "_MBCS" /I %AXIS2C_HOME%\include /c hello.c链接:
link.exe /LIBPATH:%AXIS2C_HOME%\lib axutil.lib axiom.lib axis2_parser.lib axis2_engine.lib /OUT:hello.exe *.obj
运行生成的hello.exe(此时服务端应已开启),可在服务器控制台看到客户端发来的请求及在客户端看到服务器的响应:
服务端:
客户端: