技术文章 > 服务端 > pomelo 用户指南-客户端开发 

Pomelo 客户端开发

使用 pomelo 做服务端开发时,无论什么客户端,只要能遵循与服务端的线上协议,就能够与服务端建立通信。pomelo 内建提供的 sioconnector 和 hybridconnector 都定义了自己的协议格式,其中 sioconnector 用于 socket.io 的通信,hybridconnector 则用来处理 websocket 和 tcp 的连接通信。为了方便客户端的开发,pomelo 提供了部分平台的客户端 SDK,这里主要会介绍一下用于 Web 端的 JavaScript 的 SDK 以及基于 C 语言的 libpomelo 的使用。

Web 端 JavaScript 开发库


对于浏览器来说,HTML5 中已经支持了 websocket,因此使用支持 websocket 的浏览器可以直接与服务端的 hybridconnector 建立通信。而对于比较旧的浏览器来说,还没有支持 websocket 的,可以使用基于 socket.io 的方式进行与服务端建立连接。因此,对于 Web 端,pomelo 提供了两套开发库,分别适用于支持 websocket 的浏览器和不支持 websocket 的浏览器,这两套开发库的链接如下,适用于 socket.io 的 pomelo-jsclient-socket.io 以及适用于 websocket 的 pomelo-jsclient-websocket

socket.io 的客户端开发库

对于使用 socket.io 的客户端 SDK 来说,其依赖 socket.io-client, 由于这个库在使用 component 进行管理时有 bug,因此在使用的时候,是直接引用其提供的 js 文件,具体引用的 js 文件为 socket.io-client.js。对于 pomelo-jsclient-socket.io 来说,同样也是直接使用引用其 js 文件,也即是 pomelo-client.js。在直接引用这两个文件后即可使用 pomelo 的调用了。

websocket 的客户端开发库

对于使用 websocket 的客户端 SDK 来说,使用了 component 进行管理,因此只需要配置一个 component.json 文件,里面配置相应的依赖,然后运行
$ component install
$ component build
component 会自动寻找依赖,完成客户端 js 的打包。用户只需要引用编译后的 build.js 即可,然后就可以使用 pomelo 的调用了。关于 component 的使用,请参考 component 的 wiki。我们的例子 chatofpomelo-websocket,这里就是使用了 component 来管理前端 js 的,可以作为用户使用的一个参考。

web 端 API 简介

无论是 socket.io 的还是 websocket 的,都提供了统一的 API,下面对这些 API 进行简单的介绍。
  1. pomelo.init(params, cb):
    这是往往是客户端的第一次调用,params 中应该指出要连接的服务器的 ip 和端口号,cb 会在连接成功后进行回调;
  2. pomelo.request(route, msg, cb):
    请求服务,route 为服务端的路由,格式为 "x.x.x", msg 为请求的内容,cb 会响应回来后的回调;
  3. pomelo.notify(route, msg):
    发送 notify,不需要服务器回响应的,因此没有对响应的回调,其他参数含义同 request;
  4. pomelo.on(route, cb):
    这个是从 EventEmmiter 继承过来的方法,用来对服务端的推送作出响应的。route 会用户自定义的,格式一般为 "onXXX";
  5. pomelo.disconnect():
    这个是 pomelo 主动断开连接的方法。

libpomelo


libpomelo 是 pomelo 的 c 客户端,支持 pomelo 0.3 版本以后的协议。

依赖

使用

创建客户端实例:
// create a client instance.
pc_client_t *client = pc_client_new();
添加事件监听:
// add some event callback.
pc_add_listener(client, "onHey", on_hey);
pc_add_listener(client, PC_EVENT_DISCONNECT, on_close);
监听器的定义:
// disconnect event callback.
void on_close(pc_client_t *client, const char *event, void *data) {
  printf("client closed: %d.\n", client->state);
}
连接到服务器:
struct sockaddr_in address;

memset(&address, 0, sizeof(struct sockaddr_in));
address.sin_family = AF_INET;
address.sin_port = htons(port);
address.sin_addr.s_addr = inet_addr(ip);

// try to connect to server.
if(pc_client_connect(client, &address)) {
  printf("fail to connect server.\n");
  pc_client_destroy(client);
  return 1;
}
发起一个 notify 请求:
// notified callback
void on_notified(pc_notify_t *req, int status) {
  if(status == -1) {
    printf("Fail to send notify to server.\n");
  } else {
    printf("Notify finished.\n");
  }

  // release resources
  json_t *msg = req->msg;
  json_decref(msg);
  pc_notify_destroy(req);
}

// send a notify
void do_notify(pc_client_t *client) {
  // compose notify.
  const char *route = "connector.helloHandler.hello";
  json_t *msg = json_object();
  json_t *json_str = json_string("hello");
  json_object_set(msg, "msg", json_str);
  // decref json string
  json_decref(json_str);

  pc_notify_t *notify = pc_notify_new();
  pc_notify(client, notify, route, msg, on_notified);
}
发起一个 requst 请求:
// request callback
void on_request_cb(pc_request_t *req, int status, json_t *resp) {
  if(status == -1) {
    printf("Fail to send request to server.\n");
  } else if(status == 0) {
    char *json_str = json_dumps(resp, 0);
    if(json_str != NULL) {
      printf("server response: %s\n", json_str);
      free(json_str);
    }
  }

  // release relative resource with pc_request_t
  json_t *msg = req->msg;
  pc_client_t *client = req->client;
  json_decref(msg);
  pc_request_destroy(req);

  // stop client
  pc_client_stop(client);
}

// send a request
void do_request(pc_client_t *client) {
  // compose request
  const char *route = "connector.helloHandler.hi";
  json_t *msg = json_object();
  json_t *str = json_string("hi~");
  json_object_set(msg, "msg", str);
  // decref for json object
  json_decref(str);

  pc_request_t *request = pc_request_new();
  pc_request(client, request, route, msg, on_request_cb);
}

API 接口

创建一个新的 pomelo client 实例:
pc_client_t *pc_client_new();
停止客户端的连接,该接口适合于在 libuv 子线程中调用,然后在主线程中,通过 pc_client_join 来 wait 子线程退出:
void pc_client_stop(pc_client_t *client);
销毁客户端的连接:
void pc_client_destroy(pc_client_t *client);
主线程中调用等待子线程的退出:
int pc_client_join(pc_client_t *client);
创建一个 request 请求实例:
pc_request_t *pc_request_new();
销毁一个 request 请求实例:
void pc_request_destroy(pc_request_t *req);
连接到服务器,在连接过程中会创建子线程用于处理网络 I/O:
int pc_client_connect(pc_client_t *client, struct sockaddr_in *addr);
销毁 pc_connect_t 类型的实例:
void pc_connect_req_destroy(pc_connect_t *conn_req);
发起一个 request 请求:
int pc_request(pc_client_t *client, pc_request_t *req, const char *route,
               json_t *msg, pc_request_cb cb);
创建一个 notify 请求实例:
pc_notify_t *pc_notify_new();
销毁一个 notify 请求实例:
void pc_notify_destroy(pc_notify_t *req);
发起一个 notify 请求:
int pc_notify(pc_client_t *client, pc_notify_t *req, const char *route,
              json_t *msg, pc_notify_cb cb);
添加一个事件监听:
int pc_add_listener(pc_client_t *client, const char *event,
                    pc_event_cb event_cb);
删除一个事件监听:
void pc_remove_listener(pc_client_t *client, const char *event,
                    pc_event_cb event_cb);
触发一个事件监听:
void pc_emit_event(pc_client_t *client, const char *event, void *data);

编译

前提条件:下载 gyp
gyp 其实是一个 python 写的脚本,并不需要安装,只需要下载下来,可以执行 gyp 里面的脚本就行。


来源:摘自 https://github.com/NetEase/pomelo/wiki/pomelo%E5%AE%A2%E6%88%B7%E7%AB%AF%E5%BC%80%E5%8F%91,本站 行痴 整理