jsonrpc_client.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. /*
  2. * json rpc client
  3. *
  4. * @build make jsonrpc
  5. * @server bin/jsonrpc_server 1234
  6. * @client bin/jsonrpc_client 127.0.0.1 1234 add 1 2
  7. *
  8. */
  9. #include "hloop.h"
  10. #include "hbase.h"
  11. #include "hsocket.h"
  12. #include "jsonrpc.h"
  13. #include "cJSON.h"
  14. // hloop_create_tcp_client -> on_connect -> hio_write -> hio_read -> on_recv
  15. static int verbose = 0;
  16. static unpack_setting_t jsonrpc_unpack_setting;
  17. typedef struct {
  18. char method[64];
  19. char params[2][64];
  20. } jsonrpc_call_data;
  21. static void on_close(hio_t* io) {
  22. printf("on_close fd=%d error=%d\n", hio_fd(io), hio_error(io));
  23. void* userdata = hevent_userdata(io);
  24. if (userdata) {
  25. HV_FREE(userdata);
  26. hevent_set_userdata(io, NULL);
  27. }
  28. }
  29. static void on_recv(hio_t* io, void* readbuf, int readbytes) {
  30. // printf("on_recv fd=%d readbytes=%d\n", hio_fd(io), readbytes);
  31. if (verbose) {
  32. char localaddrstr[SOCKADDR_STRLEN] = {0};
  33. char peeraddrstr[SOCKADDR_STRLEN] = {0};
  34. printf("[%s] <=> [%s]\n",
  35. SOCKADDR_STR(hio_localaddr(io), localaddrstr),
  36. SOCKADDR_STR(hio_peeraddr(io), peeraddrstr));
  37. }
  38. // unpack
  39. jsonrpc_message msg;
  40. memset(&msg, 0, sizeof(msg));
  41. int packlen = jsonrpc_unpack(&msg, readbuf, readbytes);
  42. if (packlen < 0) {
  43. printf("jsonrpc_unpack failed!\n");
  44. return;
  45. }
  46. assert(packlen == readbytes);
  47. printf("< %.*s\n", msg.head.length, msg.body);
  48. // cJSON_Parse
  49. cJSON* jres = cJSON_ParseWithLength(msg.body, msg.head.length);
  50. cJSON* jerror = cJSON_GetObjectItem(jres, "error");
  51. cJSON* jresult = cJSON_GetObjectItem(jres, "result");
  52. // ...
  53. cJSON_Delete(jres);
  54. hloop_stop(hevent_loop(io));
  55. }
  56. static void on_connect(hio_t* io) {
  57. printf("on_connect fd=%d\n", hio_fd(io));
  58. if (verbose) {
  59. char localaddrstr[SOCKADDR_STRLEN] = {0};
  60. char peeraddrstr[SOCKADDR_STRLEN] = {0};
  61. printf("connect connfd=%d [%s] => [%s]\n", hio_fd(io),
  62. SOCKADDR_STR(hio_localaddr(io), localaddrstr),
  63. SOCKADDR_STR(hio_peeraddr(io), peeraddrstr));
  64. }
  65. hio_setcb_read(io, on_recv);
  66. hio_set_unpack(io, &jsonrpc_unpack_setting);
  67. hio_read(io);
  68. jsonrpc_call_data* rpc_data = (jsonrpc_call_data*)hevent_userdata(io);
  69. assert(rpc_data != NULL);
  70. // cJSON_Print -> pack -> hio_write
  71. cJSON* jreq = cJSON_CreateObject();
  72. cJSON_AddItemToObject(jreq, "method", cJSON_CreateString(rpc_data->method));
  73. cJSON* jparams = cJSON_CreateArray();
  74. cJSON_AddItemToArray(jparams, cJSON_CreateNumber(atoi(rpc_data->params[0])));
  75. cJSON_AddItemToArray(jparams, cJSON_CreateNumber(atoi(rpc_data->params[1])));
  76. cJSON_AddItemToObject(jreq, "params", jparams);
  77. jsonrpc_message msg;
  78. memset(&msg, 0, sizeof(msg));
  79. msg.body = cJSON_PrintUnformatted(jreq);
  80. msg.head.length = strlen(msg.body);
  81. printf("> %.*s\n", msg.head.length, msg.body);
  82. // pack
  83. unsigned int packlen = jsonrpc_package_length(&msg.head);
  84. unsigned char* writebuf = NULL;
  85. HV_ALLOC(writebuf, packlen);
  86. packlen = jsonrpc_pack(&msg, writebuf, packlen);
  87. if (packlen > 0) {
  88. hio_write(io, writebuf, packlen);
  89. }
  90. cJSON_Delete(jreq);
  91. cJSON_free((void*)msg.body);
  92. HV_FREE(writebuf);
  93. HV_FREE(rpc_data);
  94. hevent_set_userdata(io, NULL);
  95. }
  96. static int jsonrpc_call(hloop_t* loop, const char* host, int port, const char* method, const char* param1, const char* param2) {
  97. hio_t* connio = hio_create(loop, host, port, SOCK_STREAM);
  98. if (connio == NULL) {
  99. return -1;
  100. }
  101. // printf("connfd=%d\n", hio_fd(connio));
  102. jsonrpc_call_data* rpc_data = NULL;
  103. HV_ALLOC_SIZEOF(rpc_data);
  104. strcpy(rpc_data->method, method);
  105. strcpy(rpc_data->params[0], param1);
  106. strcpy(rpc_data->params[1], param2);
  107. hevent_set_userdata(connio, rpc_data);
  108. hio_setcb_connect(connio, on_connect);
  109. hio_setcb_close(connio, on_close);
  110. hio_connect(connio);
  111. return 0;
  112. }
  113. int main(int argc, char** argv) {
  114. if (argc < 6) {
  115. printf("Usage: %s host port method param1 param2\n", argv[0]);
  116. printf("method = [add, sub, mul, div]\n");
  117. printf("Examples:\n");
  118. printf(" %s 127.0.0.1 1234 add 1 2\n", argv[0]);
  119. printf(" %s 127.0.0.1 1234 div 1 0\n", argv[0]);
  120. return -10;
  121. }
  122. const char* host = argv[1];
  123. int port = atoi(argv[2]);
  124. const char* method = argv[3];
  125. const char* param1 = argv[4];
  126. const char* param2 = argv[5];
  127. // init jsonrpc_unpack_setting
  128. memset(&jsonrpc_unpack_setting, 0, sizeof(unpack_setting_t));
  129. jsonrpc_unpack_setting.mode = UNPACK_BY_LENGTH_FIELD;
  130. jsonrpc_unpack_setting.package_max_length = DEFAULT_PACKAGE_MAX_LENGTH;
  131. jsonrpc_unpack_setting.body_offset = JSONRPC_HEAD_LENGTH;
  132. jsonrpc_unpack_setting.length_field_offset = 1;
  133. jsonrpc_unpack_setting.length_field_bytes = 4;
  134. jsonrpc_unpack_setting.length_field_coding = ENCODE_BY_BIG_ENDIAN;
  135. hloop_t* loop = hloop_new(0);
  136. jsonrpc_call(loop, host, port, method, param1, param2);
  137. hloop_run(loop);
  138. hloop_free(&loop);
  139. return 0;
  140. }