经过一段时间折腾,终于搞定网狐卓越版本内核引擎。源码,源码,源码。
话不多说,先上图。
代码截图
编译成功
运行效果图
下面来介绍逆向过程。
查看网狐给的头文件 KernelEngineHead.h。 和之前的版本没有太大差异,基本接口一致。
引入了webscoket服务。猜想网络传输的数据格式有变化。
通过客户端ts代码来验证。
环境安装,sdk、ndk、vs、vscode、android-studio、IDA。这里就不介绍了。
vscode查看的TcpSocket.ts
connect(host: string, port: number)
{
//设置状态
this.setConnectStatus(WebSocket.CONNECTING);
if(this.m_eSocketStatus !== 1){
//当前接口没有打开
//重新连接
var strhead = "ws://"
if (cc.sys.platform === cc.sys.WECHAT_GAME)
{
strhead = "wss://"
}
// if(cc.sys.isNative)
// {
// strhead = ""
// }
// if(cc.sys.isNative && (cc.sys.platform == cc.sys.IPHONE) || (cc.sys.platform == cc.sys.IPAD))
// {
// strhead = "ws://"
// // strEnd = "/websocket"
// }
this.m_webSocket = new WebSocket(strhead +host + ":" + port);
this.m_webSocket.onopen = this._onOpen.bind(this);
this.m_webSocket.onclose = this._onClose.bind(this);
this.m_webSocket.onmessage = this._onMessage.bind(this);
this.m_webSocket.onerror = this._onError.bind(this);
this.m_webSocket.binaryType = "arraybuffer";
console.log("connect-----", host, port);
}
return this;
}
用的 websoket通信。
private socketConnectSuccess(): void {
console.log("connectHandler: 连接成功");
// SceneManager.getInstance().hideWaitLayer();
if (this._socket.isConnected()) {
//通用版本登陆标识
var byte: MyByteArray = new MyByteArray();
byte.createBuff(128)
byte.Append_UTF16le(PublicDefine.CheckCode, 64);
this.SendData(0, 2, byte, byte.getLength());
this._SocketState = this.SocketState_Connected;
this.reConnetTimes = 30;
//大厅断线重进
// window.setTimeout(()=>{
if (PublicDefine.LOGON_PLATFROM_NULL != LogonInfo.logonType) {
GameFrameEngine.getInstance().onReconnetLogon();
}
// }, 2000);
else {
SceneManager.getInstance().hideWaitLayer();
if(this._viewFrame && this._viewFrame.onConnetSucess)
{
this._viewFrame.onConnetSucess();
}
}
}
else {
console.log("connectHandler: 连接状态异常");
}
}
BaseFrame 在连接后发送一个 验证。需要服务端做验证。
下面进入最关键的地方。
//插入消息包
public PushData(pData:MyByteArray, serverID:number)
{
this.cbBuffer = pData;
this._serverID = serverID;
if(null == pData)
{
this.wDataSize = 8 + (this._bisFirst ? 2 : 0) + (serverID > 0 ? 2 : 0);
return;
}
//计算长度
this.wDataSize = pData.getLength() + 8 + (this._bisFirst ? 2 : 0) + (serverID > 0 ? 2 : 0);
}
public SendData(wMainCmdID: number, wSubCmdID: number, pData: MyByteArray = null, wDataSize: number = 0): void {
if (this._socket == null) {
return;
}
var buffer: CMD_Data = new CMD_Data(this._isFirst);
buffer.wMainCmdID = wMainCmdID;
buffer.wSubCmdID = wSubCmdID;
buffer.wDataType = 2;
buffer.cbCheckCode = 0;
if (wMainCmdID > 200 && wMainCmdID <= 300) {
buffer.PushData(pData, GlobalUserItem.nCurrentServerID);
}
else {
buffer.PushData(pData, 0);
}
this._socket.send(buffer.toByteArray());
this._isFirst = false;
return;
}
//将消息包转换为array
public toByteArray():ArrayBuffer
{
var myByteArray = new MyByteArray();
myByteArray.createBuff(this.wDataSize);
myByteArray.Append_Byte(this.cbCheckCode);
myByteArray.Append_Byte(this.wDataType);
myByteArray.Append_UInt16(this.wDataSize);
myByteArray.Append_UInt16(this.wMainCmdID);
myByteArray.Append_UInt16(this.wSubCmdID);
if(this._bisFirst)
{
myByteArray.Append_UInt16(4);
}
if(this._serverID > 0) //如果是存在游戏服ID,表示是游戏服消息,加上server
{
myByteArray.Append_UInt16(this._serverID);
}
if(null != this.cbBuffer)
{
myByteArray.Append_Array(this.cbBuffer.getArrayBuffer());
}
return myByteArray.getArrayBuffer();
}
整体的数据头格式和以前没有太大改变
在初次发送数据长度多加2个字节(验证命令)。进入具体子游戏时候会多加2个字节。表示 wServerID。这里猜想。是告诉服务器连接哪个子游戏服务。使用的长连接,没有之前版本的256数组的映射。
服务端要实现webscoket。webscoket具体要参照C++实现WebSocket解析协议
部分服务端代码
检测socket类型。
webscoket 握手部分
验证部分
去掉256字节的map映射
到此基本完工