文章目录
一、环境搭建
需要的资源如下:
libev,jsonrpc-c
https://codeload.github.com/enki/libev/zip/refs/heads/master
https://codeload.github.com/hmng/jsonrpc-c/zip/refs/heads/master
1.编译libev,jsonrpc
参考:编译jsonrpc
lib_make.sh
#!/bin/sh
# @Author: yyh
# @Date: 2023-03-13 12:55:16
# @Last Modified by: yyh
# @Last Modified time: 2023-03-13 14:22:45
sudo mkdir ~/lib_srouce_code/
case $1 in
"libev")
cp libev-master.zip ~/lib_srouce_code/
cd ~/lib_srouce_code/
unzip -x libev-master.zip -d ~/lib_srouce_code/
cd ~/lib_srouce_code/libev-master
if [ $2 = "ubuntu" ] ; then
#ubuntu16.04
sudo mkdir compile_result_ubuntu16/
./configure --prefix=$(pwd)/compile_result_ubuntu16
elif [ $2 = "mipsel" ]; then
#mipsel
sudo mkdir compile_result_mipsel/
./configure --prefix=$(pwd)/compile_result_mipsel --host=mipsel-openwrt-linux CC=/opt/toolchain-mipsel_24kc_gcc-8.4.0_musl/bin/mipsel-openwrt-linux-gcc CXX=/opt/toolchain-mipsel_24kc_gcc-8.4.0_musl/bin/mipsel-openwrt-linux-musl-g++
`STAGING_DIR=/opt/toolchain-mipsel_24kc_gcc-8.4.0_musl/`
fi
sudo make clean
sudo make
sudo make install
;;
"jsonrpc")
cp jsonrpc-c-arma_stable.tar.gz ~/lib_srouce_code/
tar -xzvf jsonrpc-c-arma_stable.tar.gz -C ~/lib_srouce_code/
cd ~/lib_srouce_code/jsonrpc-c-arma_stable
autoreconf -i
if [[ $2 = "ubuntu" ]]; then
#ubuntu16.04
sudo mkdir compile_result_ubuntu16/
./configure --prefix=$(pwd)/compile_result_ubuntu16 --enable-shared
# elif [[ $2 = "mipsel" ]]; then
# #mipsel
# sudo mkdir compile_result_mipsel/
# ./configure --prefix=$(pwd)/compile_result_mipsel --host=mipsel-openwrt-linux CC=/opt/toolchain-mipsel_24kc_gcc-8.4.0_musl/bin/mipsel-openwrt-linux-gcc CXX=/opt/toolchain-mipsel_24kc_gcc-8.4.0_musl/bin/mipsel-openwrt-linux-musl-g++
# `STAGING_DIR=/opt/toolchain-mipsel_24kc_gcc-8.4.0_musl/`
fi
sudo make clean
sudo make
sudo make install
;;
"install") #先编译libev和jsonrpc-c,后install,编译目标环境需一致
if [ $2 = "ubuntu" ]; then
sudo mkdir ubuntu_test_code/
sudo cp ~/lib_srouce_code/libev-master/compile_result_ubuntu16/* ./ubuntu_test_code -rf -p #-p 保留源文件或目录的属性
sudo cp ~/lib_srouce_code/jsonrpc-c-arma_stable/compile_result_ubuntu16/* ./ubuntu_test_code -rf -p
elif [ $2 = "mipsel" ]; then
sudo mkdir mipsel_test_code/
sudo cp ~/lib_srouce_code/jsonrpc-c-arma_stable/src/*.c ./mipsel_test_code -rf -p
sudo cp ~/lib_srouce_code/jsonrpc-c-arma_stable/include/*.h ./mipsel_test_code -rf -p
sudo cp ~/lib_srouce_code/libev-master/compile_result_mipsel/* ./mipsel_test_code -rf -p #-p 保留源文件或目录的属性
sudo cp ./mipsel_test_code/lib/libev.so.4.0.0 ./mipsel_test_code/lib/libev.so
sudo cp ./mipsel_test_code/lib/libev.so.4.0.0 ./mipsel_test_code/lib/libev.so.4
sudo cp ./mipsel_test_code/*.h ./mipsel_test_code/include/
# sudo cp ~/lib_srouce_code/jsonrpc-c-arma_stable/compile_result_mipsel/* ./mipsel_test_code -rf -p
fi
;;
# *) echo '你没有输入 1 到 4 之间的数字'
# ;;
esac
##./lib_make.sh libev mipsel
##./lib_make.sh install mipsel
##./lib_make.sh libev ubuntu
##./lib_make.sh jsonrpc ubuntu
##./lib_make.sh install ubuntu
2.交叉编译
./lib_make.sh libev mipsel
./lib_make.sh install mipsel
进入mipsel_test_code目录相关文件如下
二、编译并运行代码
1.makefile
CC=/opt/toolchain-mipsel_24kc_gcc-8.4.0_musl/bin/mipsel-openwrt-linux-gcc
# LIBEV_DIR=/home/yyh/lib_srouce_code/libev-master/compile_result_mipsel
LIBEV_DIR=.
LIBEV_DIR=.
CFLAGS = -I${LIBEV_DIR}/include -L${LIBEV_DIR}/lib
LDAGS = -lev
TARGET = test
all:
$(CC) -o $(TARGET) *.c $(CFLAGS) $(LDAGS)
.PHONY:clean
clean:
rm -rf *.o $(TARGET)
2.server.c
/*
* @Author: yyh
* @Date: 2023-03-11 16:00:39
* @Last Modified by: yyh
* @Last Modified time: 2023-03-13 12:49:36
*/
#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
#define GET_KEY_SIZE 10 //键值对 键参数个数
#define STRKEY_SIZE 20 //键的大小
#define STRVAL_SIZE 20 //值的大小
struct jrpc_server my_server;
cJSON *my_root;
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!" );
}
static char *get_key(char *s)//从一个json object对象中获取key
{
char key[STRKEY_SIZE];
char *pf,*pb;
int len;
pf=strchr(s, '\"');
pb=strchr(pf+1, '\"');
len = pb - pf - 1;
memcpy(key, pf + 1, len);
key[len]='\0';
return strdup(key);
}
//echo "{\"method\":\"state_set\",\"params\":[{\"hello\":\"world\"}],\"id\":\"2\"}" | nc localhost 1234
cJSON * mystate_set(jrpc_context * ctx, cJSON * params, cJSON *id) { //设置键值对
if(params == NULL){//获取参数失败
ctx->error_code = 1;
ctx->error_message=strdup("err_key)");
ctx->data = strdup("err_value");
return NULL;
}
int arrSize=cJSON_GetArraySize(params);//设置的获取参数个数
int i,j;
cJSON *vals,*dst_val;
if(params->type == cJSON_Array){
for(i=0;i<arrSize;i++) { //获取每个参数对象
vals = cJSON_GetArrayItem(params,i);
if(vals->type == cJSON_Object){
char *s = cJSON_PrintUnformatted(vals); //将一个jison object对象转为字符串
char *key = get_key(s); //获取json object对象中的key
cJSON *value = cJSON_GetObjectItem(vals,key);//通过key获取值
if(value == NULL){
return cJSON_CreateString("bad key! bad value!");//格式错误
}
cJSON *item = cJSON_GetObjectItem(my_root,key);
if(item != NULL) //如果原来json数据中存在该键值则删除
cJSON_DeleteItemFromObject(my_root,key);
cJSON_AddItemToObject(my_root,key,cJSON_CreateString(value->valuestring));//添加新的键值对
free(s);
free(key);
}
}
}
return cJSON_CreateString("set success!");
}
//echo "{\"method\":\"state_get\",\"params\":[\"hello\"],\"id\":\"1\"}" | nc localhost 1234
cJSON * mystate_get( jrpc_context * ctx, cJSON * params, cJSON *id) { //通过键获取值
if(params == NULL){
ctx->error_code = 1;
ctx->error_message=strdup("err_key)");
ctx->data = strdup("err_value");
return NULL;
}
int arrSize=cJSON_GetArraySize(params);
char *get_key[GET_KEY_SIZE];
char *res_val[GET_KEY_SIZE];
int i,j;
cJSON *vals,*dst_val;
if(params->type == cJSON_Array){
for(i=0;i<arrSize;i++) {
vals = cJSON_GetArrayItem(params,i);
if(vals->type == cJSON_String){
get_key[i]=vals->valuestring;
}
}
}
int count=0;
for(j=0;j<i;j++)
{
dst_val=cJSON_GetObjectItem(my_root,get_key[j]);
if(dst_val != NULL)
{
if(dst_val->type = cJSON_String)
{
res_val[count++]=dst_val->valuestring;
}
}
}
cJSON *res;
res = cJSON_CreateArray(); //创建result参数返回对应值
for(j=0;j<count;j++)
{
cJSON_AddItemToArray(res,cJSON_CreateString(res_val[j]));
}
if(cJSON_GetArraySize(res) == 0) //没有找到对应的value
{
ctx->error_code = 1;
ctx->error_message=strdup("no such value!");
return NULL;
}
return res;
}
int main( void ) {
jrpc_server_init(&my_server, PORT);
//创建原始数据 json格式
my_root = cJSON_CreateObject();
cJSON_AddItemToObject(my_root,"jsonrpc",cJSON_CreateString("2.0"));
cJSON_AddItemToObject(my_root,"method",cJSON_CreateString("DeviceUpLoadInfo"));
cJSON_AddItemToObject(my_root,"id",cJSON_CreateString("76BFCDDE4D2C"));
cJSON_AddItemToObject(my_root,"params",cJSON_CreateString("src"));
cJSON_AddItemToObject(my_root,"ip",cJSON_CreateString("192.168.5.148"));
cJSON_AddItemToObject(my_root,"time",cJSON_CreateString("2023-3-1 18:02:41"));
cJSON_AddItemToObject(my_root,"rfidinfo",cJSON_CreateString("075583849888190308020911_e280110c20007781e8440985_000000000000000000000000"));
cJSON_AddItemToObject(my_root,"picType",cJSON_CreateString("src"));
cJSON_AddItemToObject(my_root,"picdata",cJSON_CreateString("person123"));
cJSON_AddItemToObject(my_root,"hello",cJSON_CreateString("world"));
//注冊俩方法
jrpc_register_procedure(&my_server, say_hello, "sayHello" , NULL );
jrpc_register_procedure(&my_server, mystate_set,"state_set",NULL);
jrpc_register_procedure(&my_server, mystate_get,"state_get",NULL);
jrpc_register_procedure(&my_server, exit_server, "exit" , NULL );
jrpc_server_run(&my_server);
jrpc_server_destroy(&my_server);
return 0;
}
3.编译测试
#!/bin/sh
# @Author: yyh
# @Date: 2023-03-13 14:42:11
# @Last Modified by: yyh
# @Last Modified time: 2023-03-13 14:53:56
PC_IP=192.168.5.148
MYLIBDIR=/tmp/lib
MYINCDIR=/tmp/include
my_eth=eth0.1
# string=`ifconfig $my_eth`
# string=${string#*inet addr:}
# string=${string%% Bcast*}
# echo $string
# string=192.168.5.241
cd /tmp
chmod 0777 /tmp/*
mkdir $MYLIBDIR -p
mkdir $MYINCDIR -p
if [ $1 = "get_lib" ]
cd $MYLIBDIR
tftp -g -r libev.a $PC_IP
tftp -g -r libev.la $PC_IP
tftp -g -r libev.so $PC_IP
tftp -g -r libev.so.4 $PC_IP
tftp -g -r libev.so.4.0.0 $PC_IP
elif [ $1 = "get_inc" ]
then
cd $MYINCDIR
tftp -g -r cJSON.h $PC_IP
tftp -g -r jsonrpc-c.h $PC_IP
tftp -g -r event.h $PC_IP
tftp -g -r ev++.h $PC_IP
tftp -g -r ev.h $PC_IP
elif [ $1 = "get_test" ]
then
tftp -g -r test $PC_IP
chmod 0777 ./*
elif [ $1 = "path_set" ]
then
export C_INCLUDE_PATH=$C_INCLUDE_PATH:/tmp/include
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/tmp/lib
echo $C_INCLUDE_PATH
echo $LD_LIBRARY_PATH
fi
chmod 0777 /tmp/*
测试结果如下
运行./test
PC运行测试脚本
三、jsonrpc相关概念
JSON-RPC,是一个无状态且轻量级的远程过程调用(RPC)传送协议,其传递内容透过 JSON 为主
请求对象
一个请求对象包含下列成员:
jsonrpc
method
params
id
注意:
params参数结构必须是数组,或者数组对象
例如:
"params":["hello","world"]
"params":[{"hello":"world"},{"key":"value"}]
响应对象
jsonrpc
result
error
id
注意:
响应对象必须包含 result 或 error 字段,但两个字段不能同时存在。
错误对象
code
message
data