16.1 测试链接属性

  1. 我们在基于lars_reactor开发的时候,可能有时候需要在写消息回调的时候,希望conn绑定一些属性。现在我们可以配置这种功能到`net_connection`上。

lars_reactor/include/net_connection.h

  1. #pragma once
  2. #include <stdio.h>
  3. /*
  4. *
  5. * 网络通信的抽象类,任何需要进行收发消息的模块,都可以实现该类
  6. *
  7. * */
  8. class net_connection
  9. {
  10. public:
  11. net_connection():param(NULL) {}
  12. //发送消息的接口
  13. virtual int send_message(const char *data, int datalen, int msgid) = 0;
  14. virtual int get_fd() = 0;
  15. void *param; //TCP客户端可以 通过该参数传递一些自定义的参数
  16. };
  17. //创建链接/销毁链接 要触发的 回调函数类型
  18. typedef void (*conn_callback)(net_connection *conn, void *args);
  1. 这里我们给`net_connection`类添加了一个`param`属性,这样,我们就可以绑定一些开发者自定义的参数和当前链接进行绑定。注意,这里也提供了一个`get_fd()`的纯虚函数,目的是提供conn获取当前fd的数据。

16.2 完成Lars Reactor V0.12开发

server端

  1. #include "tcp_server.h"
  2. #include <string>
  3. #include <string.h>
  4. #include "config_file.h"
  5. tcp_server *server;
  6. //回显业务的回调函数
  7. void callback_busi(const char *data, uint32_t len, int msgid, net_connection *conn, void *user_data)
  8. {
  9. printf("callback_busi ...\n");
  10. //直接回显
  11. conn->send_message(data, len, msgid);
  12. printf("conn param = %s\n", (const char *)conn->param);
  13. }
  14. //打印信息回调函数
  15. void print_busi(const char *data, uint32_t len, int msgid, net_connection *conn, void *user_data)
  16. {
  17. printf("recv client: [%s]\n", data);
  18. printf("msgid: [%d]\n", msgid);
  19. printf("len: [%d]\n", len);
  20. }
  21. //新客户端创建的回调
  22. void on_client_build(net_connection *conn, void *args)
  23. {
  24. int msgid = 101;
  25. const char *msg = "welcome! you online..";
  26. conn->send_message(msg, strlen(msg), msgid);
  27. //将当前的net_connection 绑定一个自定义参数,供我们开发者使用
  28. const char *conn_param_test = "I am the conn for you!";
  29. conn->param = (void*)conn_param_test;
  30. }
  31. //客户端销毁的回调
  32. void on_client_lost(net_connection *conn, void *args)
  33. {
  34. printf("connection is lost !\n");
  35. }
  36. int main()
  37. {
  38. event_loop loop;
  39. //加载配置文件
  40. config_file::setPath("./serv.conf");
  41. std::string ip = config_file::instance()->GetString("reactor", "ip", "0.0.0.0");
  42. short port = config_file::instance()->GetNumber("reactor", "port", 8888);
  43. printf("ip = %s, port = %d\n", ip.c_str(), port);
  44. server = new tcp_server(&loop, ip.c_str(), port);
  45. //注册消息业务路由
  46. server->add_msg_router(1, callback_busi);
  47. server->add_msg_router(2, print_busi);
  48. //注册链接hook回调
  49. server->set_conn_start(on_client_build);
  50. server->set_conn_close(on_client_lost);
  51. loop.event_process();
  52. return 0;
  53. }
  1. 我们在 `on_client_build`中,对创建链接做了conn的参数传递,然后通过路由业务的转发,我们在`callback_busi`中,得到了之前传递进去的参数。这样对我们使用框架做一些复杂的业务,需要绑定一些属性给conn是有必要的。

client端

  1. #include "tcp_client.h"
  2. #include <stdio.h>
  3. #include <string.h>
  4. //客户端业务
  5. void busi(const char *data, uint32_t len, int msgid, net_connection *conn, void *user_data)
  6. {
  7. //得到服务端回执的数据
  8. char *str = NULL;
  9. str = (char*)malloc(len+1);
  10. memset(str, 0, len+1);
  11. memcpy(str, data, len);
  12. printf("recv server: [%s]\n", str);
  13. printf("msgid: [%d]\n", msgid);
  14. printf("len: [%d]\n", len);
  15. }
  16. //客户端销毁的回调
  17. void on_client_build(net_connection *conn, void *args)
  18. {
  19. int msgid = 1;
  20. const char *msg = "Hello Lars!";
  21. conn->send_message(msg, strlen(msg), msgid);
  22. }
  23. //客户端销毁的回调
  24. void on_client_lost(net_connection *conn, void *args)
  25. {
  26. printf("on_client_lost...\n");
  27. printf("Client is lost!\n");
  28. }
  29. int main()
  30. {
  31. event_loop loop;
  32. //创建tcp客户端
  33. tcp_client client(&loop, "127.0.0.1", 7777, "clientv0.6");
  34. //注册消息路由业务
  35. client.add_msg_router(1, busi);
  36. client.add_msg_router(101, busi);
  37. //设置hook函数
  38. client.set_conn_start(on_client_build);
  39. client.set_conn_close(on_client_lost);
  40. //开启事件监听
  41. loop.event_process();
  42. return 0;
  43. }
  1. 和之前的client无任何改变。

运行结果

  • 服务端:
  1. $ ./server
  2. msg_router init...
  3. ip = 127.0.0.1, port = 7777
  4. create 0 thread
  5. create 1 thread
  6. create 2 thread
  7. create 3 thread
  8. create 4 thread
  9. add msg cb msgid = 1
  10. add msg cb msgid = 2
  11. begin accept
  12. begin accept
  13. [thread]: get new connection succ!
  14. callback_busi ...
  15. conn param = I am the conn for you!
  1. 会发现我们是可以在callback中拿到conn的属性