c语言rpc框架源码,libsearpc: 简单易用的 C 语言 RPC 框架,包括客户端和服务器端(包括 Python实现)...

Searpc是一个基于GObject系统的C语言RPC框架,使用JSON格式进行序列化/反序列化。用户需要提供传输部分。每个RPC函数在服务器端需要额外的GError参数来报告错误。客户端创建rpc_client并指定传输函数,通过rpc_client调用服务器端定义的函数。服务器端初始化searpc服务,注册函数,并处理请求和返回结果。该框架支持客户端和服务器之间的JSON数据交互。
摘要由CSDN通过智能技术生成

Introduction

Searpc is a simple C language RPC framework based on GObject system. Searpc

handles the serialization/deserialization part of RPC, the transport

part is left to users.

The serialization/deserialization uses JSON format via json-glib

library. A serialized json object is returned from server to client

after executing the RPC function. Each RPC function defined in the

server side should take an extra GError argument to report error. The

returned json object contains three fields:

ret: the return value of the RPC function

err_code: error code. This field is only set if the RPC function

reports an error.

err_msg: error message. This field is only set if the RPC function

reports an error.

Compile

Just

./autogen.sh; ./configure; make; make install

To enable profile, Use

CFLAGS="-DPROFILE" ./configure

When profile is enabled, the time spend in each rpc call will be printed.

Example

Client

In the client side, you need to:

Create a rpc_client and supply the transport function.

write code to send the request to server and get the resonpse from it.

Create rpc_client

The client needs to create a SearpcClient object and supply a

transport function. For example:

/* create an rpc_client and supply the transport function. */

SearpcClient *rpc_client;

rpc_client = searpc_client_new();

rpc_client->transport = transport_callback;

rpc_client->arg = &sockfd;

Suppose we have a get_substring function defined in server as follows:

gchar *get_substring (const gchar *orig_str, int sub_len, GError **error)

To call this function, we type:

gchar* result;

GError *error = NULL;

result = searpc_client_call__string (client, "get_substring", &error,

2, "string", "hello", "int", 2);

string in searpc_client_call__string specify the return type. "get_substring"

is the function name. The remain parameters specify the number of parameters the rpc

function took and the type of each parameter and its value. So

2, "string", "hello", "int", 2

means "get_substring" takes 2 parameters, the first is of type "string", the value is

"hello", the second is of type "int", the value is 2.

Transport function

When the client-side function is called, Searpc does the following work:

Pack the function name and the params into JSON data format.

Call your transport function to send the JSON data

to the server, and get the returned data from the server.

Unpack the returned JSON data and return the value as the return

value of the client-side function.

Your transport function is supposed to:

Send the request data to the server.

Receive the returned data from the server.

The prototype of the transport function is:

/*

* arg: rpc_client->arg. Normally a socket number.

* fcall_str: the JSON data stream generated by Searpc.

* fcall_len: the length of `fcall_str`.

* ret_len: place to get the length of the returned json data stream.

* Returns: A newly allocated string stores the JSON data stream.

*/

static char *transport_callback (void *arg, const char *fcall_str, size_t fcall_len, size_t *ret_len);

Server

In the server side, you need to:

Init searpc server

Create services and register your functions

write code to receive the request and send the result

And Searpc handles the others for you.

Concepts

Marshal: The process of unpacking the function arguments from

JSON data, call the RPC function and packing the result into JSON

data format is called marshalling. The function used to

pack the result is called a marshal.

Signature: Every function has a signature determined by its

return type and parameter types. Knowning a function's signature

enable us to use a corresponding marshal to call it and convert

the result into json string.

Init Searpc Server

First write rpc_table.py to contain the rpc function signatures as follows:

# [ , [] ]

func_table = [

[ "int", ["string"] ],

[ "string", ["int", "string"] ],

]

Add makefile rule:

searpc-signature.h searpc-marshal.h: rpc_table.py

python searpc-codegen.py rpc_table.py

searpc-signature.h and searpc-marshal.h will be created containing the

function signatures and corresponding marshals. searpc-marshal.h also contains

a function called register_marshals.

Then we init the server as follows:

#include "searpc-signature.h"

#include "searpc-marshal.h"

static void

init_rpc_service(void)

{

/* register_marshals is defined in searpc-marshal.h */

searpc_server_init(register_marshals);

}

Register Functions

To register a function we first need to create a service. A service is

a set of functions.

Suppose we want to make searpc_strlen callable from some network

clients, we can do this by putting the following code somewhere:

static int

searpc_strlen(const char *str)

{

if (str == NULL)

return -1;

else

return strlen(str);

}

static void

register_functions()

{

searpc_create_service("searpc-demo");

/* The first parameter is the implementation function.

* The second parameter is the name of the rpc function the

* client would call.

* The third parameter is the signature.

*/

searpc_server_register_function("searpc-demo",

searpc_strlen,

"searpc_strlen",

searpc_signature_int__string());

}

The seaprc_server_register_function routine registers a function as

a RPC function. The

prototype of this function is:

/*

* service: the name of the service

* func: pointer to the function you want to register

* fname: the name of the function. It would be the key of your

* function in the fucntion hash table.

* signature: the identifier used to get the corresponding marshal.

* Returns: a gboolean value indicating success or failure

*/

gboolean searpc_server_register_function (const char *service,

void* func,

const gchar *fname,

gchar *signature);

Call the RPC fucntion

After the registration, you should listen to the socket and wait for the

incoming request data stream. Once you get a valid request, call the

searpc_server_call_function() routine, which will automatically do the

following work for you:

Parse the JSON data stream to resolve the function name and the data.

Lookup the function in internal function table according to the funcname.

If a proper function is found, call the function with the given params.

Packing the result into a JSON data string.

The prototype of searpc_server_call_function is:

/*

* service: Service name.

* data: The incoming JSON data stream.

* len: The length of **`data`**.

* ret_len: Place to hold the length of the JSON data stream to be returned

* Returns: The JSON data containing the result of the RPC

*/

gchar* searpc_server_call_function (const char *service,

gchar *data, gsize len, gsize *ret_len)

The value returned by searpc_server_call_function() is the JSON data

ready to send back to the client.

Note, the JSON data stream from client does not contain the service

name, it's left to the transport layer to solve the problem. There are

several ways, for example:

You may listen on different sockets and determine the service by

the incoming socket.

The client transport function prepend the service name into the request

before the json data, and the server transport function first read the service

name and read the json data.

Pysearpc

Pysearpc is the Python binding of Searpc. Only the client side function is

supported. To use it, simply define a class which inherits SearpcClient, and

provide a call_remote_func_sync method, which is equivalent to the

transport_callback.

To define your RPC funtion, use the @searpc_func decorator. It is

equivalent to SEARPC_CLIENT_DEFUN_XXX__YYY macro. To define a RPC

function which accepts multiple params, here is an example:

class SampeSearpcClient(SearpcClient):

def call_remote_func_sync(self, fcall_str):

# your transport code here

...

@searpc_func("int", ["string", "string"])

def searpc_demo_func(self):

# this is enough for the client side

pass

See the demo program for a more detailed example.

Demos

There are well-commented demos in both C and Python.

searpc-demo-server.c: The server side demo program

searpc-demo-client.c: The client side demo in C

pysearpc-demo-client.py: The client side demo in Python

To run the demo, run the server demo in a shell, and run the client

demo in another. To run the python demo, you should first install the

package and setup the PYTHONPATH appropriately.

Dependency

The following packages are required to build libsearpc:

glib-2.0 >= 2.26.0

gobject-2.0 >= 2.26.0

jansson >= 2.2.1

python simplejson (for pysearpc)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值