## 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)
原創書籍: [http://www.hmoore.net/@aceld](http://www.hmoore.net/@aceld)

>**原創聲明:未經作者允許請勿轉載, 如果轉載請注明出處**
- 一、Lars系統概述
- 第1章-概述
- 第2章-項目目錄構建
- 二、Reactor模型服務器框架
- 第1章-項目結構與V0.1雛形
- 第2章-內存管理與Buffer封裝
- 第3章-事件觸發EventLoop
- 第4章-鏈接與消息封裝
- 第5章-Client客戶端模型
- 第6章-連接管理及限制
- 第7章-消息業務路由分發機制
- 第8章-鏈接創建/銷毀Hook機制
- 第9章-消息任務隊列與線程池
- 第10章-配置文件讀寫功能
- 第11章-udp服務與客戶端
- 第12章-數據傳輸協議protocol buffer
- 第13章-QPS性能測試
- 第14章-異步消息任務機制
- 第15章-鏈接屬性設置功能
- 三、Lars系統之DNSService
- 第1章-Lars-dns簡介
- 第2章-數據庫創建
- 第3章-項目目錄結構及環境構建
- 第4章-Route結構的定義
- 第5章-獲取Route信息
- 第6章-Route訂閱模式
- 第7章-Backend Thread實時監控
- 四、Lars系統之Report Service
- 第1章-項目概述-數據表及proto3協議定義
- 第2章-獲取report上報數據
- 第3章-存儲線程池及消息隊列
- 五、Lars系統之LoadBalance Agent
- 第1章-項目概述及構建
- 第2章-主模塊業務結構搭建
- 第3章-Report與Dns Client設計與實現
- 第4章-負載均衡模塊基礎設計
- 第5章-負載均衡獲取Host主機信息API
- 第6章-負載均衡上報Host主機信息API
- 第7章-過期窗口清理與過載超時(V0.5)
- 第8章-定期拉取最新路由信息(V0.6)
- 第9章-負載均衡獲取Route信息API(0.7)
- 第10章-API初始化接口(V0.8)
- 第11章-Lars Agent性能測試工具
- 第12章- Lars啟動工具腳本