启动本地服务 cd 到 server文件夹中执行 python start_server.py
命令
Mars是微信提供的终端基础组件,是跨平台的
主要包括以下几个部分
- comm : 基础库,包括
socket
、线程、消息队列、协程等基础工具 - Xlog : 通用日志模块,提供高性能、高可用、安全性、容错性的日志功能
- SDT : 网络诊断模块
- STN : 信令传输网络模块,负责终端与服务器的小数据信令通道。
消息核心流程:一个消息任务以startTask开始,onTaskEnd结束。中间通过StnCallBack::Req2Buf与StnCallBack::Buf2Resp分别处理客户端的请求和响应的相关操作,比如数据处理,服务端响应和状态检测等等。
项目配置
- 安装 cmake 和 XCode 以及 python2.7.x
- python build_ios.py 生成配置文件
- 数据传输使用谷歌的protocol buffer
- 添加依赖库
- CoreTelephony.framework
- UIKit.framework
- Foundation.framework
- libz.tbd
- SystemConfiguration.frmaework
- libresolv9.tbd
- mars.framework(由Mars提供的库)
STN 网络模块初始化
- 涉及初始化方法,在
didFinishLaunchingWithOptions
中调用
在初始化时必须先调用setCallback
方法,最后在调用onForeground
和makesureLongLinkConnect
中间的顺序可以随意
注意:STN 默认是后台,在初始化 STN 后需要主动调用一次BaseEvent.onForeground(true)
程序退出或进入后台时,释放STN
调用
mars::baseevent::OnDestroy();
- (void)setCallBack {
mars::stn::SetCallback(mars::stn::StnCallBack::Instance());
mars::app::SetCallback(mars::app::AppCallBack::Instance());
}
- (void) createMars {
mars::baseevent::OnCreate();
}
- (void)setClientVersion:(UInt32)clientVersion {
mars::stn::SetClientVersion(clientVersion);
}
- (void)setShortLinkDebugIP:(NSString *)IP port:(const unsigned short)port {
std::string ipAddress([IP UTF8String]);
mars::stn::SetShortlinkSvrAddr(port, ipAddress);
}
- (void)setShortLinkPort:(const unsigned short)port {
mars::stn::SetShortlinkSvrAddr(port);
}
- (void)setLongLinkAddress:(NSString *)string port:(const unsigned short)port debugIP:(NSString *)IP {
std::string ipAddress([string UTF8String]);
std::string debugIP([IP UTF8String]);
std::vector<uint16_t> ports;
ports.push_back(port);
mars::stn::SetLonglinkSvrAddr(ipAddress,ports,debugIP);
}
- (void)setLongLinkAddress:(NSString *)string port:(const unsigned short)port {
std::string ipAddress([string UTF8String]);
std::vector<uint16_t> ports;
ports.push_back(port);
mars::stn::SetLonglinkSvrAddr(ipAddress,ports);
}
数据处理
集成的时候加上日志打印 xlog
,在 main
中添加,因使用c++
将 main.m
,改为main.mm
,方便排查问题
NSString* logPath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingString:@"/log"];
// set do not backup for logpath
const char* attrName = "com.apple.MobileBackup";
u_int8_t attrValue = 1;
setxattr([logPath UTF8String], attrName, &attrValue, sizeof(attrValue), 0, 0);
// init xlog
#if DEBUG
xlogger_SetLevel(kLevelDebug);
appender_set_console_log(true);
#else
xlogger_SetLevel(kLevelInfo);
appender_set_console_log(false);
#endif
appender_open(kAppednerAsync, [logPath UTF8String], "Test", "");
- 开启一个任务
// ChannelType_LongConn 通道 有长链、短链或者两者
// IM_CMD_LOGIN CIMID号,自定义表示那种任务
// LONG_LINK_HOST_PROT 长链地址
// CGIURL 短链地址
CGITask * task = [[CGITask alloc] initAll:ChannelType_LongConn AndCmdId:IM_CMD_LOGIN AndCGIUri:CGIURL AndHost:LONG_LINK_HOST_PROT];
[[NetworkService sharedInstance] startTask:task ForUI:self];
task 中关键字
- taskid 任务的唯一标识,自动生成
- channel_select 标识是长连接还是短连接获取两者,属性有:
ChannelType_ShortConn, ChannelType_LongConn, ChannelType_All
- cgi 短连的utl, 短连的必填
- cmid: 长连的cgi命令号,用于标识长连请求的cgi 如: IM_CMD_LOGIN
- 发送数据
requestSendData
向服务端发送数据,这里是发起登录请求
- (NSData *)requestSendData{
// 自定义的一个pb解析类,和自定义些参数
ImLogin * login = [[ImLogin alloc] init];
Head * heads = [[Head alloc] init];
heads.cmd = IM_CMD_LOGIN;
heads.seq = 1;
heads.version = 200;
heads.flag = 0;
// 这里是做登录的,传相应的参数给服务端
login.head = heads;
login.no = @"ABC";
login.token = @"abcd";
login.timestamp = 829374432;
login.devId = 37489237434;
login.role = ROLE;
login.platformId = 1;
// 将数据转为data
NSData * data = [login data];
return data;
}
- 收到服务返回
- (int)onPostDecode:(NSData *)responseData{
NSError * error;
// 登录pb解析类,解析数据
ImLoginRes * loginRes = [ImLoginRes parseFromData:responseData error:&error];
// 这里返回 200 表示登录成功
if (loginRes.code == 200) {
dispatch_async(dispatch_get_main_queue(), ^{
NSInteger uid = loginRes.uid;
self.uids = loginRes.uid;
if (self.iMLoginUserIdBlock) {
self.iMLoginUserIdBlock(uid);
}
});
// 可做登录后的事,如:保存消息偏移量或发起消息同步等
}
return loginRes.code == 200 ? 0 : -1;
}
- (int)onTaskEnd:(uint32_t)tid errType:(uint32_t)errtype errCode:(uint32_t)errcode{
return 0;
}
- 修改心跳设置
longlink_packer.cc
修改这个方法
uint32_t (*longlink_noop_interval)() = []() -> uint32_t { return 1 * 60 * 1000; };
当return
为0时,会执行Mars
自己的心跳逻辑
- 设置用户名
为保持心跳的连接频率,需设置用户名,否则Mars
会降低请求的频率
AccountInfo AppCallBack::GetAccountInfo() {
AccountInfo info;
info.username = "wxy";
info.uin = 11984;
return info;
}
- 出现C++方法中未定义的错误
修改Build Setting
->Apple Clang - Language - c++