最近对json-rpc比较感兴趣,思想很简单,而且看到了很多不同语言的实现。在github上 hmngomes 的 json-rpc-c (实现的是server端,基于TCP流),短小精悍,提供了很好的框架,代码十分清晰,易于扩展,而且代码容易看懂,很经典。该实现依赖于其它两个库 libev 和 cJSON,值得认真学习。
测试的时候先启动server,而后通过 nc 命令发送相应的json格式数据,就会有相应的效果:
vonzhou@de15:~$ echo "{\"method\":\"sayHello\"}" | nc localhost 1234
{
"result": "Hello!"
}
vonzhou@de15:~$ echo "{\"method\":\"exit\"}" | nc localhost 1234
{
"result": "Bye!"
}
{
"result": "Hello!"
}
vonzhou@de15:~$ echo "{\"method\":\"exit\"}" | nc localhost 1234
{
"result": "Bye!"
}
下面贴出代码,便于温习。
-------------------server.c
#include
<stdio.h>
#include
<stdlib.h>
#include
<unistd.h>
#include
<errno.h>
#include
<string.h>
#include
<sys/types.h>
#include
<sys/socket.h>
#include
<netinet/in.h>
#include
<netdb.h>
#include
<arpa/inet.h>
#include
<sys/wait.h>
#include
<signal.h>
#include
"jsonrpc-c.h"
#define
PORT 1234
// the port users will be connecting to
struct
jrpc_server my_server;
cJSON * say_hello(
jrpc_context
* ctx, cJSON * params, cJSON *id) {
return
cJSON_CreateString(
"Hello!"
);
}
cJSON * exit_server(
jrpc_context
* ctx, cJSON * params, cJSON *id) {
jrpc_server_stop(&my_server);
return
cJSON_CreateString(
"Bye!"
);
}
int
main(
void
) {
jrpc_server_init(&my_server, PORT);
//注册俩方法
jrpc_register_procedure(&my_server, say_hello,
"sayHello"
, NULL );
jrpc_register_procedure(&my_server, exit_server,
"exit"
, NULL );
jrpc_server_run(&my_server);
jrpc_server_destroy(&my_server);
return
0;
}
-----------------json-rpc.h
#ifndef
JSONRPCC_H_
#define
JSONRPCC_H_
#include
"cJSON.h"
#include
<ev.h>
/*
*
* http://www.jsonrpc.org/specification
*
* code message meaning
* -32700 Parse error Invalid JSON was received by the server.
* An error occurred on the server while parsing the JSON text.
* -32600 Invalid Request The JSON sent is not a valid Request object.
* -32601 Method not found The method does not exist / is not available.
* -32602 Invalid paramsInvalid method parameter(s).
* -32603 Internal errorInternal JSON-RPC error.
* -32000 to -32099Server error Reserved for implementation-defined server-errors.
*/
#define
JRPC_PARSE_ERROR -32700
#define
JRPC_INVALID_REQUEST -32600
#define
JRPC_METHOD_NOT_FOUND -32601
#define
JRPC_INVALID_PARAMS -32603
#define
JRPC_INTERNAL_ERROR -32693
typedef
struct
{
void
*
data
;
int
error_code
;
char
*
error_message
;
}
jrpc_context
;
//JSON方法类型
typedef
cJSON* (*
jrpc_function
)(
jrpc_context
*context, cJSON *params, cJSON* id);
struct
jrpc_procedure {
char
*
name
; //方法名
jrpc_function
function
; //方法地址
void
*
data
; //额外信息
};
struct
jrpc_server {
int
port_number
;
struct
ev_loop *
loop
; //eventloop类型
ev_io
listen_watcher
; //
int
procedure_count
;
struct
jrpc_procedure *
procedures
;
int
debug_level
;
};
struct
jrpc_connection {
struct
ev_io
io
;
int
fd
;
int
pos
;
//记录在buffer中的位置
unsigned
int
buffer_size
;
char
*
buffer
;
int
debug_level
;
};
int
jrpc_server_init(
struct
jrpc_server *server,
int
port_number);
int
jrpc_server_init_with_ev_loop(
struct
jrpc_server *server,
int
port_number,
struct
ev_loop *loop);
static
int
__jrpc_server_start (
struct
jrpc_server *server);
void
jrpc_server_run(
struct
jrpc_server *server);
int
jrpc_server_stop(
struct
jrpc_server *server);
void
jrpc_server_destroy(
struct
jrpc_server *server);
static
void
jrpc_procedure_destroy (
struct
jrpc_procedure *procedure);
int
jrpc_register_procedure(
struct
jrpc_server *server,
jrpc_function
function_pointer,
char
*name,
void
*data);
int
jrpc_deregister_procedure(
struct
jrpc_server *server,
char
*name);
#endif
-----------------json-rpc.c
#include
<stdio.h>
#include