🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
## 16) 链接属性设置功能 ### 16.1 测试链接属性 ​ 我们在基于lars_reactor开发的时候,可能有时候需要在写消息回调的时候,希望conn绑定一些属性。现在我们可以配置这种功能到`net_connection`上。 > lars_reactor/include/net_connection.h ```c #pragma once #include <stdio.h> /* * * 网络通信的抽象类,任何需要进行收发消息的模块,都可以实现该类 * * */ class net_connection { public: net_connection():param(NULL) {} //发送消息的接口 virtual int send_message(const char *data, int datalen, int msgid) = 0; virtual int get_fd() = 0; void *param; //TCP客户端可以 通过该参数传递一些自定义的参数 }; //创建链接/销毁链接 要触发的 回调函数类型 typedef void (*conn_callback)(net_connection *conn, void *args); ``` ​ 这里我们给`net_connection`类添加了一个`param`属性,这样,我们就可以绑定一些开发者自定义的参数和当前链接进行绑定。注意,这里也提供了一个`get_fd()`的纯虚函数,目的是提供conn获取当前fd的数据。 ### 16.2 完成Lars Reactor V0.12开发 ### server端 ```c #include "tcp_server.h" #include <string> #include <string.h> #include "config_file.h" tcp_server *server; //回显业务的回调函数 void callback_busi(const char *data, uint32_t len, int msgid, net_connection *conn, void *user_data) { printf("callback_busi ...\n"); //直接回显 conn->send_message(data, len, msgid); printf("conn param = %s\n", (const char *)conn->param); } //打印信息回调函数 void print_busi(const char *data, uint32_t len, int msgid, net_connection *conn, void *user_data) { printf("recv client: [%s]\n", data); printf("msgid: [%d]\n", msgid); printf("len: [%d]\n", len); } //新客户端创建的回调 void on_client_build(net_connection *conn, void *args) { int msgid = 101; const char *msg = "welcome! you online.."; conn->send_message(msg, strlen(msg), msgid); //将当前的net_connection 绑定一个自定义参数,供我们开发者使用 const char *conn_param_test = "I am the conn for you!"; conn->param = (void*)conn_param_test; } //客户端销毁的回调 void on_client_lost(net_connection *conn, void *args) { printf("connection is lost !\n"); } int main() { event_loop loop; //加载配置文件 config_file::setPath("./serv.conf"); std::string ip = config_file::instance()->GetString("reactor", "ip", "0.0.0.0"); short port = config_file::instance()->GetNumber("reactor", "port", 8888); printf("ip = %s, port = %d\n", ip.c_str(), port); server = new tcp_server(&loop, ip.c_str(), port); //注册消息业务路由 server->add_msg_router(1, callback_busi); server->add_msg_router(2, print_busi); //注册链接hook回调 server->set_conn_start(on_client_build); server->set_conn_close(on_client_lost); loop.event_process(); return 0; } ``` ​ 我们在 `on_client_build`中,对创建链接做了conn的参数传递,然后通过路由业务的转发,我们在`callback_busi`中,得到了之前传递进去的参数。这样对我们使用框架做一些复杂的业务,需要绑定一些属性给conn是有必要的。 ### client端 ```c #include "tcp_client.h" #include <stdio.h> #include <string.h> //客户端业务 void busi(const char *data, uint32_t len, int msgid, net_connection *conn, void *user_data) { //得到服务端回执的数据 char *str = NULL; str = (char*)malloc(len+1); memset(str, 0, len+1); memcpy(str, data, len); printf("recv server: [%s]\n", str); printf("msgid: [%d]\n", msgid); printf("len: [%d]\n", len); } //客户端销毁的回调 void on_client_build(net_connection *conn, void *args) { int msgid = 1; const char *msg = "Hello Lars!"; conn->send_message(msg, strlen(msg), msgid); } //客户端销毁的回调 void on_client_lost(net_connection *conn, void *args) { printf("on_client_lost...\n"); printf("Client is lost!\n"); } int main() { event_loop loop; //创建tcp客户端 tcp_client client(&loop, "127.0.0.1", 7777, "clientv0.6"); //注册消息路由业务 client.add_msg_router(1, busi); client.add_msg_router(101, busi); //设置hook函数 client.set_conn_start(on_client_build); client.set_conn_close(on_client_lost); //开启事件监听 loop.event_process(); return 0; } ``` ​ 和之前的client无任何改变。 ### 运行结果 - 服务端: ```c $ ./server msg_router init... ip = 127.0.0.1, port = 7777 create 0 thread create 1 thread create 2 thread create 3 thread create 4 thread add msg cb msgid = 1 add msg cb msgid = 2 begin accept begin accept [thread]: get new connection succ! callback_busi ... conn param = I am the conn for you! ``` ​ 会发现我们是可以在callback中拿到conn的属性 --- ### 关于作者: 作者:`Aceld(刘丹冰)` mail: [danbing.at@gmail.com](mailto:danbing.at@gmail.com) github: [https://github.com/aceld](https://github.com/aceld) 原创书籍: [https://www.kancloud.cn/@aceld](https://www.kancloud.cn/@aceld) ![](https://img.kancloud.cn/b0/d1/b0d11a21ba62e96aef1c11d5bfff2cf8_227x227.jpg) >**原创声明:未经作者允许请勿转载, 如果转载请注明出处**