Hessian 是一种二进制 Web 服务协议,以其高效、简洁和跨语言的特性而闻名,相比于 XML-based 的 SOAP 或文本格式的 JSON,Hessian 的二进制格式使其在网络传输和解析速度上具有显著优势。

在 C 语言生态中,最著名和广泛使用的 Hessian 库是 C-Hessian,下面我将围绕这个库,从概念、环境搭建、API 使用到完整示例,为你提供一个全面的指南。
什么是 Hessian?
Hessian 是一种轻量级的二进制 Web 服务协议,它定义了一种客户端和服务器之间如何序列化和反序列化对象的方法。
-
优点:
- 高效: 二进制格式,数据量小,解析速度快。
- 简洁: 没有复杂的 XML 标签,协议本身很简单。
- 跨语言: 支持多种编程语言(Java, Python, C++, C, .NET, Ruby 等)。
- 基于 HTTP: 可以轻松穿透防火墙。
-
缺点:
(图片来源网络,侵删)- 可读性差: 二进制数据无法直接用肉眼查看和调试(不像 JSON 或 XML)。
- 生态较小: 相比于 REST/JSON,社区和工具支持相对较少。
C-Hessian 库简介
C-Hessian 是一个用 C 语言实现的 Hessian 客户端库,它允许你从 C 程序中调用远程的 Hessian 服务,这个库遵循 MIT 许可证,是开源的。
- 项目地址:
https://github.com/cyang/c-hessian - 功能: 它主要负责 Hessian 协议的底层细节,如对象序列化、网络通信等,让你可以方便地构建和发送 Hessian 请求。
环境搭建
1 安装 C-Hessian 库
最简单的方式是使用包管理器,在基于 Debian/Ubuntu 的系统上:
sudo apt-get update sudo apt-get install libhessian-dev
如果你需要从源码编译,可以克隆 GitHub 仓库并按照其 README.md 文件进行编译安装。
2 准备开发环境
确保你的系统已经安装了 C 语言编译器(如 gcc)和构建工具(如 make)。

# 检查 gcc gcc --version # 检查 make make --version
核心概念与 API
C-Hessian 的使用流程通常如下:
- 创建客户端 (
hessian_client_new): 指定服务的 URL。 - 调用方法 (
hessian_call): 指定要调用的方法名,并传入参数。 - 处理返回值: 方法调用会返回一个
hessian_value结构体,你需要根据预期的返回类型(如整数、字符串、对象等)来解析它。 - 释放资源 (
hessian_value_free,hessian_client_free): 释放所有分配的内存,防止内存泄漏。
关键数据结构: hessian_value
hessian_value 是 C-Hessian 中处理所有数据(输入参数和返回值)的核心结构体。
typedef struct {
int type; // 数据类型: Hessian_TYPE_INT, Hessian_TYPE_STRING, etc.
union {
int i_val;
char *s_val;
// ... 其他类型的值
} v;
} hessian_value;
常用 API
| API 函数 | 描述 |
|---|---|
hessian_client_new(const char *url) |
创建一个新的 Hessian 客户端实例,连接到指定的 URL。 |
hessian_call(hessian_client *client, const char *method, ...) |
调用远程服务的方法,参数是可变的,需要与 hessian_value 结构体指针匹配。 |
hessian_value_free(hessian_value *value) |
释放 hessian_value 结构体及其内部动态分配的内存(如字符串)。非常重要! |
hessian_client_free(hessian_client *client) |
关闭客户端连接并释放客户端资源。 |
常用数据类型宏
| 宏 | 描述 |
|---|---|
HESSIAN_TYPE_INT |
整型 |
HESSIAN_TYPE_STRING |
字符串 |
HESSIAN_TYPE_BOOL |
布尔值 |
HESSIAN_TYPE_NULL |
空值 |
HESSIAN_TYPE_MAP |
键值对映射 |
HESSIAN_TYPE_LIST |
列表/数组 |
完整示例
假设我们有一个简单的 Hessian 服务,它提供两个功能:
sayHello(name: String) -> String: 返回 "Hello, [name]!"add(a: int, b: int) -> int: 返回 a + b 的和。
1 服务端 (Java 示例)
为了方便测试,我们先写一个简单的 Java Hessian 服务,你需要 Hessian 的 Java 库。
// HelloService.java
public interface HelloService {
String sayHello(String name);
int add(int a, int b);
}
// HelloServiceImpl.java
public class HelloServiceImpl implements HelloService {
@Override
public String sayHello(String name) {
return "Hello, " + name + "!";
}
@Override
public int add(int a, int b) {
return a + b;
}
}
// Server.java (启动服务)
import com.caucho.hessian.server.HessianServlet;
import javax.servlet.http.HttpServlet;
public class Server extends HttpServlet {
public static void main(String[] args) {
// 实际项目中,你会把它部署到 Tomcat 或 Jetty 等 Servlet 容器中
// 这里简化说明,你需要一个 Web 服务器来运行这个 Servlet
System.out.println("Hessian Server is running on http://localhost:8080/hello");
}
}
(注意:这个 Java 服务需要部署到 Servlet 容器中才能运行。)
2 C 语言客户端
我们用 C 语言来调用这个服务。
文件: hessian_client_example.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <hessian.h> // 包含 C-Hessian 头文件
// 函数声明,用于错误处理
void handle_error(const char *msg);
int main() {
// 1. 创建 Hessian 客户端
// 假设服务部署在 http://localhost:8080/hello
hessian_client *client = hessian_client_new("http://localhost:8080/hello");
if (!client) {
handle_error("Failed to create Hessian client.");
return 1;
}
printf("Hessian client created successfully.\n");
// --- 调用 sayHello 方法 ---
printf("\n--- Calling sayHello ---\n");
// 2. 准备参数
hessian_value name_arg;
name_arg.type = HESSIAN_TYPE_STRING;
name_arg.v.s_val = strdup("World"); // strdup 为字符串分配内存
// 3. 调用方法
hessian_value result = hessian_call(client, "sayHello", &name_arg, NULL);
// 4. 检查和处理返回值
if (result.type == HESSIAN_TYPE_STRING) {
printf("Result from sayHello: %s\n", result.v.s_val);
} else {
printf("Error: sayHello returned unexpected type.\n");
}
// 5. 释放参数和返回值的内存
free(name_arg.v.s_val);
hessian_value_free(&result);
// --- 调用 add 方法 ---
printf("\n--- Calling add ---\n");
// 2. 准备参数
hessian_value a_arg, b_arg;
a_arg.type = HESSIAN_TYPE_INT;
a_arg.v.i_val = 10;
b_arg.type = HESSIAN_TYPE_INT;
b_arg.v.i_val = 20;
// 3. 调用方法
hessian_value sum_result = hessian_call(client, "add", &a_arg, &b_arg, NULL);
// 4. 检查和处理返回值
if (sum_result.type == HESSIAN_TYPE_INT) {
printf("Result from add: %d\n", sum_result.v.i_val);
} else {
printf("Error: add returned unexpected type.\n");
}
// 5. 释放返回值的内存 (参数是基本类型,无需 free)
hessian_value_free(&sum_result);
// 6. 关闭客户端
hessian_client_free(client);
printf("\nClient finished.\n");
return 0;
}
// 简单的错误处理函数
void handle_error(const char *msg) {
fprintf(stderr, "Error: %s\n", msg);
exit(EXIT_FAILURE);
}
3 编译和运行
-
编译: 使用
gcc编译,并链接hessian库。gcc hessian_client_example.c -o hessian_client_example -lhessian
-
运行:
- 首先,确保你的 Java Hessian 服务正在运行(在 Tomcat 的 8080 端口上)。
- 然后,运行编译好的 C 程序。
./hessian_client_example
预期输出:
Hessian client created successfully.
--- Calling sayHello ---
Result from sayHello: Hello, World!
--- Calling add ---
Result from add: 30
Client finished.
重要注意事项
- 内存管理: 这是 C 语言编程的重中之重,每次使用
strdup或从hessian_call中获取字符串时,你都必须负责调用free或hessian_value_free来释放内存,忘记释放会导致内存泄漏。 - 错误处理: 示例中的错误处理很简单,在实际应用中,你需要检查
hessian_call的返回值,并根据result.type和可能存在的错误代码来更健壮地处理各种异常情况(如网络错误、服务端抛出异常等)。 - 复杂类型: 对于 Map、List、自定义对象等复杂类型,C-Hessian 提供了更底层的 API(如
hessian_value_new_map)来手动构建这些结构,这比处理基本类型要复杂,需要仔细阅读 C-Hessian 的源码或文档。 - 依赖: C-Hessian 可能依赖于一些网络库(如 libcurl)来进行 HTTP 通信,确保你的系统上安装了所有必要的依赖。
使用 C 语言通过 Hessian 协议调用 Web 服务,核心就是 C-Hessian 库,其基本流程是:
创建客户端 -> 构建 hessian_value 参数 -> 调用 hessian_call -> 解析返回的 hessian_value -> 释放所有内存。
虽然它比高级语言(如 Python/Java)使用起来更繁琐,需要手动管理内存,但对于性能要求极高或运行在资源受限环境(如嵌入式系统)的 C Hessian 是一个非常高效的选择。
