英雄联盟死机问题有时启动就死机。应用程序日志出这个错误有关系吗?怎么解决

为什么我家电脑玩其他游戏没事、一玩英雄联盟就蓝屏死机呢? 以前都不会这样!
(太子少师)
(太子少师)
追问:我试试! 先 追问:正常的吧!& 回答:电脑用了几年了?也不能排除电脑使用寿命的问题 & 你在重装下系统吧 如果是win7 的话就重装win7 &现在免win10 &但是有不兼容的现象 & 装下win7试下 &在360就有重装导航 追问:电脑前几个月 &新装的!& 回答:C盘 内存还剩多少 &? 追问:10G 多点吧!& 回答:我的C盘都是剩余将近30G左右的 &处了系统文件其他都不放C盘 要是还不行就去维修店咨询下吧 让他给你看看 & & &实在不行就换战斗机 &买个高配置的玩剑灵五档都流畅的机子&
(太子少师)
0x0000003F/A/1A/2E 内存类 & & 0x0000003F/A/1A/2E错误表示内存管理遇到了问题。这个错误一般是因为内存执行了错误的I/O(输入/输出)操作,存在BUG的硬件设备驱动程序错误地使用了内存资源,某个应用软件被错误地分配了大量的内核内存等原因引起的。如果遇到0x0000003F错误,建议检查一下最近有没有安装过新的应用软件或硬件设备驱动程序。如果有的话,请将最近安装过的应用软件(特别是磁盘优化软件及杀毒软件)或驱动程序逐一卸载,看看问题能否解决。 0X0000007B/ED 硬盘类 & & 此类两种错误是典型的由硬盘引起的故障,也是兼容模式有问题的代表。我们在BIOS内把硬盘格式改为IDE兼容模式,可以有效的解决7B错误,更改后如果依然蓝屏,那问题有可能上升到了病毒造成硬盘引导分区损坏,恢复方法只有重新安装系统了。 OxC0000005 未知故障/超频/兼容报错 & & 以C大头的错误举例,此类蓝屏大多数与硬件无关,它主要来源于系统内部数据冲突或者驱动方面重复等问题。例如盘符划分重复,F盘改为E盘,启动时无法找到原F盘的路径产生崩溃,在不改变盘符名称的前提下(多少有些兜圈子),划分出一个新的盘符或者插入一个U盘作为系统写入存储盘(代替原F盘),错误便可以解决。在例如一些新驱动的更新,与老驱动反生冲突,多发生在外置声卡或网卡上,如果出现C开头的报错,网友可以对比借鉴,删除老驱动或者重新安装新驱动。 0x0000009F/A5 电源类 & & 错误表示计算机的电源遇到了问题。这个错误通常发生在关机、重启、待机、休眠等与计算机电源有关的操作时,一般是因为电源有问题或ACPI高级电源选项配置不正确引起的。如果遇到0x0000009F错误,建议检查一下计算机的ACPI高级电源选项配置是否正确。请在主板BIOS设置中检查ACPI高级电源选项是否已经设置为“Enabled”,然后为Windows重新安装主板芯片组驱动程序 0x000000BE/C2/D1/EA 设备驱动BUG类 & & 此类错误表示内核程序或硬件设备的驱动程序试图进行错误的内存操作。这个错误一般是因为应用软件或硬件设备驱动程序存在BUG或者不兼容引起的。如果遇到此类错误,建议首先检查一下最近有没有安装新的应用软件或硬件设备驱动程序。如果有的话,请将最近安装过的应用软件或驱动程序逐一卸载或重新安装,看看问题能否解决;如果方法无效,我们又将回到内存硬盘类的错误范围内,但几乎此类蓝屏现象与硬件关系不大。 & & 其中EA项代表着显卡与显示器间的兼容错误,除了卸载或重新安装驱动意外,还应当针对显示器的接口对主板PCIE和AGP接口进行查看,是否可以正常工作。 追问:忘记看这个了! &我等会在上游戏 &卡蓝屏一次才知道!&
(太子少师)
如果是梦幻这类不吃配置的游戏,lol用i3cpu还是会发烫的,那你可能是风扇问题,导致cpu过热,这样才死机的,建议拆开清灰或者换风扇,还有一种可能就是你近期电脑被碰撞过,不管怎么样还是拆了看看吧;如果是玩大型游戏正常,就英雄联盟蓝屏司机,不会是游戏包安装不完全,游戏包安装不完全可能会死机,但是不会蓝屏,可能是英雄联盟所需的插件不够(如flash或abode版本过低),或者驱动问题 补充: 以前都能玩,不存在是配置问题,这种配置,开最低配是够用了,换句话说就算是开高配置,最多是卡,不会死机。我觉得发热的可能性最大,看看风扇会不会转 追问: 逆战 & QQ飞车 &擦不多把! & 电脑没碰撞过 & 有时候会蓝屏 &一般都是卡死 &卡在一个界面然后有奇怪的声音一直持续! & &怎么弄就没用只有按重启键!& 追问: 我拆开过电脑 &风扇都会转的!& 追问: 包括电脑卡主的时候 & 电脑里面也没有什么问题!& 回答: 你这么说我就明白了,玩逆战、qq飞车偶尔会蓝屏,那英雄联盟蓝屏是正常的,lol更吃配置,这是你cpu不够用了,原来可以玩是因为你新买的,这个cpu刚好可以带的动,但是负荷过大,发热、老损快(特别是笔记本),你玩了几个月之后,已经老损了,加上游戏更新,对配置要求更高了,所以你的cpu已经带不动了,如果你是台式机,花点钱换个i5cpu就行,如果是笔记本,转手卖了换新的 追问: 我说 &逆战 &QQ飞车都不会蓝屏 & 回答: 你把所有软件都关掉,这个图截图给我看看 追问: 我在玩逆战!& 追问: 反正出了玩英雄联盟 & &怎么都不会 &蓝屏死机什么的! &我也是郁闷了!& 追问:
& 哥们加我QQ & 聊把!& 回答: cpu和内存都没问题,可以带动英雄联盟,你又说电脑没碰撞过,那我给你个最笨的方法,但是绝对有效,先把杀毒软件、安全防护软件都关掉玩试试看,360有时候会默认禁止腾讯的一些游戏,如果玩不了,就下个驱动精灵,把所有的驱动都更新一遍,再玩玩试试看,如果还是不行,重装系统,游戏重新下载,绝对管用,因为你硬件是没有任何问题的
(太子少师)
他们的回答好长
(太子少师)
如果是电脑没问题,玩其他游戏也不会蓝屏的话,可能有几个原因,1是可能电脑里面有病毒,二是可能电脑配置问题,三的话可能是游戏问题,可能是游戏文件缺失导致不能正常运行,可以尝试卸载以后重新安装一遍 追问:我昨天就是吧游戏删除之后重新下的! & 还是不行!& 回答:那就是电脑配置跟不上了,如果电脑没病毒的话,你试试把配置全部调低,或者玩玩高配游戏看看是否也会蓝屏闪退,一般蓝屏的情况都是电脑负荷过大
(太子少师)
显卡应该有问题。CPU过高。 追问:那是我测试热量的图片正常没那么高!&
可输入10000个汉字
上传图片:
[经验值&50可以上传图片]
可输入50个汉字
同类未解决问题
同类已解决问题osx平台上lol英雄联盟launcher启动器的分析实现 - 推酷
osx平台上lol英雄联盟launcher启动器的分析实现
我算个LOL玩家吧,虽然是郊区白银段位的,虽然能1打5个电脑,但瘾不小。每次想打LOL,都找不到PC电脑,看着OSX却不能玩国服,只能玩美服、韩服。而外服的网络延迟比较大,根本没法打,跳帧严重,野怪都打不过。每次瘾来了时,总是想在OSX上也能玩,次数多了,决定试试,看看能否在OSX上玩国服。
15年10月份对LOL英雄联盟录像做过解析器
,文中最后提到过关于LOL客户端架构的组成,以及在OSX上打LOL国服还是有可能的。
现状分析,League of legends有mac版本,在riot拳头运营的地区中,有韩服、美服、欧服之类国外服务器。而腾讯运营国服版,却没有OSX版本。上次的录像分析中,是腾讯运营的windows版本产生的录像文件,可以在OSX版本的美服上解析、渲染、播放,也就以为着协议是相通的,也就意味着用riot运营的OSX客户端,连接腾讯运营的服务器,应该可以正常通讯,正常游戏的。
先来看下国服League of legends英雄联盟的目录结构
国服LOL目录结构
Air目录为LolClient.exe所在目录,即游戏大厅目录,air的,也就是flash as的,意味着反编译比较简单…
Config目录确定
Cross目录为腾讯游戏必装的各种乱七八糟工具包目录
Game目录为game进程League of legends.exe所在目录
log目录,我也不知道这是记录啥日志的,一直是空的
logs目录,这是launcher启动器记录通讯数据的目录
TCLS目录是腾讯登录SSO的客户端程序目录
TQM目录,腾讯自己的,跟游戏无关
先来对比Windows跟osx上区别,riot运营的(以下以美服代表)游戏,是先选地区,再进入登录界面,再进入游戏。而腾讯运营的是先登录,再选择大区,再进入游戏。显然,腾讯运营的选大区,可以理解为riot运营的选地区,之后再进入游戏。区别是riot先选区,再登录;腾讯(以下简称国服)的先登录,再选区。先看国服在windows上流程,快捷方式打开的是 TCLS\Client.exe ,内嵌登录的DLL,登录之后,选大区,直接开启LolClient.exe进入对应大区游戏。而美服的登录窗口是在LolClient.exe中完成的,不难看出区别是美服手动登录,国服自动登录。显然,是LolClient.exe启动时,CLI参数包含了一些KEY,来实现了自动登录。
也就是说,问题在登录认证部分,只要我在OSX上能实现LolClient.exe的自动登录就可以…当然要在windows上获取登录的Game Signature Key,先来看下win上的进程启动信息:
英雄联盟在windows上登录时的CLI参数
果然是CLI中参数带有signature key,参数如下:
Air\LolClient.exe -runtime .\ -nodebug META-INF\AIR\application.xml .\ -- 8393 gameSignatureLength=120
szGameSignature=DBF2EF3C9F53FFD8DFCD6B08C8291ED9FEA0395EEF92E1CCF80D0A76AC4B6DD4E039DB9D2B84EAC0AB881FFFCD32CCED53C44DCF698E9CD636EE732F5EC2B077F5D6006824FAA5EFF8
cltkeyLength=16 cltkey=h4.ac}w)gsq53_6Y uId= --host=hn1-new-feapp. --xmpp_server_url=hn1-new-ejabberd.
--lq_uri=https://hn1-new-login.:8443 --getClientIpURL=http://183.60.165.214/get_ip.php
可以看出,除了Air运行时参数外,还有8393数字,认证的KEY,当前大区服务器域名,xmpp聊天服务器地址,登录服务器地址之类。另外,在看下LolClient.exe的进程树:
lol在windows上的进程树
如上图,游戏大厅进程LolClient.exe跟game进程League of legends.exe都是lol.launcher_tencent.exe的子进程。
这里的8393数字其实是LolClient.exe要连接的TCP端口,也就是 lol.launcher_tencent.exe 进程监听的端口, lol.launcher_tencent.exe 进程再fork起 LolClient.exe 进程,进入游戏大厅。
游戏开局匹配时,都是在
LolClient.exe 中进行的,匹配完成之后 ,
lol.launcher_tencent.exe
又createprocess出
Game\League of Legends.exe
进入游戏。
那么,只要我在osx上实现一个launcher的功能,就能在osx上玩League of legends英雄联盟的国服了,感觉很兴奋的样子,继续往下看……
LolClient.exe进程进入游戏后, lol.launcher_tencent.exe 进程是如何知道的呢?它又是如何决定启动League of Legends.exe进程的?在上篇
中,提到过,game进程启动时,命令行参数有个端口 8394 ,先查看进程监听列表
C:\Users\chenchi&tasklist|find &lol.launcher_tencent.exe&
lol.launcher_tencent.exe
5416 Console
C:\Users\chenchi&netstat -anto |find &5416&
127.0.0.1:8393
127.0.0.1:8393
127.0.0.1:2552
ESTABLISHED
127.0.0.1:8394
127.0.0.1:8395
从结果中,可以看到进程 lol.launcher_tencent.exe 监听了本地的、8395端口,而且, LolClient.exe 已经连接了8393端口,也就是其启动时命令行参数中的对应数值。那么另外两个端口也应该是其他进程来连接的咯。抓本地数据包,看看他们之间有没有通讯,如看看他们通讯了什么内容:(在windows上,wireshark抓不到回环地址通讯包,可以用rawcap来抓包)
E:\crt_download\ProcessMonitor&RawCap.exe 127.0.0.1 localhost-.pcapng
Sniffing IP : 127.0.0.1
: localhost-.pcapng
之后,wireshark打开这个文件,可以看到如下TCP数据包:
lol-launcher-tentcent.exe与LolClient.exe的通讯TCP数据包
00 00 00 01 00 00 00
04 00 00 00 00 00 00 00 ........ ........
00 00 00 01 00 00 00
04 00 00 00 00 00 00 00 ........ ........
00 00 00 01 00 00 00
05 00 00 00 00 00 00 00 ........ ........
00 00 00 01 00 00 00
00 00 00 00 34 00 00 00 ........ ....4...
34 2e 31 37 2e 32 33
2e 39 34 20 35 31 35 36 14.17.23 .94 5156
51 62 77 41 34 73 6f
42 38 4a 71 37 43 4f 45
QbwA4so B8Jq7COE
2b 31 78 63 34 67 3d
3d 20 34 30 30 36 33 31 Q+1xc4g= = 400631
从协议包结果上来看,对比发送、接收的4个包作为例子,不难看出,他们的数据包格式拆分为前8bytes 10 00 00 00 01 00 00 00 为固定值(暂且认为是固定值);后面4bytes 04 00 00 00 、 05 00 00 00 为一段;再后面的4bytes 00 00 00 00 、 34 00 00 00 为另一段;最后一部分的Nbytes长度 31 34 2e 31 37 2e 32 33 2e 39 34 20 35 31 35 36 20 51 62 77 41 34 73 6f 42 38 4a 71 37 43 4f 45 51 2b 31 78 63 34 67 3d 3d 20 34 30 30 36 33 31 39 32 33 32 为最后一段;以第4个通讯包来看,第三段的对应数值是 0x34 ,显然是LittleEndian小端字节序,显然后面的
部分数据长度也是 0x34 个,也就是说,协议通讯格式的第三段表示后面消息包长度的含义,第四段就是主体消息正文。第一段、第二段都是消息头的部分。第二段多数为command指令。暂且这么假设,那么通讯协议包格式确定了,接下来就要确认下每个command对应的业务含义了。先看下LolClient.exe进程发给launcher,跟League of legends.exe发给launcher进程的TCP数据包,初步确认下我对协议包格式的判断是否正确
聊天消息转发
如何查找command的类型一共有多少种?如何确认每种command的意义?记得最初LOL目录结构里提到大厅客户端LolClient.exe是flash air的,反编译比较方便,入口文件是LolClient.swf,跟下去是mod/win/ClientWindow.dat,然后加载了&^*($#@#,as代码太乱了,而且,都分布在各个小的flash中,目录还不统一,拓展名还都是dat的,还得手动改成swf,反编译工具才能选它,as代码也不好理解,检索麻烦,索性直接反编译 lol.launcher_tencent.exe 进程吧。
IDA的导入 lol.launcher_tencent.exe 进程后,在imports中看到 Maestro_Remove、…等来自RiotLauncher这个library
lol-launcher-tencent.exe导入了RiotLauncher.dll
再静态分析RiotLauncher.dll,在Exports里看到Maestro_MessageTypeToString函数
RiotLauncher.dll中Maestro_MessageTypeToString
跟进,看到 MAESTROMESSAGETYPE_GAMECLIENT_CREATE 等字样
RiotLauncher.dll中MAESTROMESSAGETYPE_GAMECLIENT_CREATE
riotlauncher-dll-MM-type-to-string-2
signed int __cdecl Maestro_MessageTypeToString(int a1, char *a2, rsize_t a3)
char *v4; // [sp-8h] [bp-8h]@2
switch ( a1 )
v4 = &MAESTROMESSAGETYPE_GAMECLIENT_CREATE&;
v4 = &MAESTROMESSAGETYPE_GAMECLIENT_STOPPED&;
v4 = &MAESTROMESSAGETYPE_GAMECLIENT_CRASHED&;
v4 = &MAESTROMESSAGETYPE_GAMECLIENT_ABANDONED&;
v4 = &MAESTROMESSAGETYPE_GAMECLIENT_LAUNCHED&;
v4 = &MAESTROMESSAGETYPE_GAMECLIENT_VERSION_MISMATCH&;
v4 = &MAESTROMESSAGETYPE_GAMECLIENT_CONNECTED_TO_SERVER&;
v4 = &MAESTROMESSAGETYPE_CLOSE&;
v4 = &MAESTROMESSAGETYPE_HEARTBEAT&;
v4 = &MAESTROMESSAGETYPE_REPLY&;
v4 = &MAESTROMESSAGETYPE_LAUNCHERCLIENT&;
v4 = &MAESTROMESSAGETYPE_CHATMESSAGE_TO_GAME&;
v4 = &MAESTROMESSAGETYPE_CHATMESSAGE_FROM_GAME&;
v4 = &MAESTROMESSAGETYPE_PLAY_REPLAY&;
v4 = &MAESTROMESSAGETYPE_GAMECLIENT_CREATE_VERSION&;
v4 = &MAESTROMESSAGETYPE_GAMECLIENT_INSTALL_VERSION&;
v4 = &MAESTROMESSAGETYPE_GAMECLIENT_CANCEL_INSTALL&;
v4 = &MAESTROMESSAGETYPE_GAMECLIENT_INSTALL_PROGRESS&;
v4 = &MAESTROMESSAGETYPE_GAMECLIENT_INSTALL_PREVIEW&;
v4 = &MAESTROMESSAGETYPE_GAMECLIENT_CANCEL_PREVIEW&;
v4 = &MAESTROMESSAGETYPE_GAMECLIENT_PREVIEW_PROGRESS&;
v4 = &MAESTROMESSAGETYPE_GAMECLIENT_UNINSTALL_VERSION&;
v4 = &MAESTROMESSAGETYPE_GAMECLIENT_CANCEL_UNINSTALL&;
v4 = &MAESTROMESSAGETYPE_GAMECLIENT_UNINSTALL_PROGRESS&;
v4 = &MAESTROMESSAGETYPE_GAMECLIENT_UNINSTALL_PREVIEW&;
v4 = &MAESTROMESSAGETYPE_GAMECLIENT_CANCEL_UNINSTALL_PREVIEW&;
v4 = &MAESTROMESSAGETYPE_GAMECLIENT_PREVIEW_UNINSTALL_PROGRESS&;
v4 = &MAESTROMESSAGETYPE_GAMECLIENT_ENUMERATE_INSTALLED_VERSIONS&;
v4 = &MAESTROMESSAGETYPE_GAMECLIENT_CREATE_CLIENT_AND_PRELOAD&;
v4 = &MAESTROMESSAGETYPE_GAMECLIENT_UPDATE_PRELOADED_GAME_WITH_CREDENTIALS&;
v4 = &MAESTROMESSAGETYPE_GAMECLIENT_INITIAL_PRELOAD_COMPLETE&;
v4 = &MAESTROMESSAGETYPE_GAMECLIENT_UPDATE_PLAYER_CONNECTION&;
v4 = &MAESTROMESSAGETYPE_GAMECLIENT_PLAY_PRELOADED_GAME&;
v4 = &MAESTROMESSAGETYPE_GAMECLIENT_GAME_LOADING_COMPLETE&;
v4 = &MAESTROMESSAGETYPE_KILL_GAMECLIENT_PROCESS&;
v4 = &MAESTROMESSAGETYPE_GAMECLIENT_ENUMERATE_UNINSTALLABLE_VERSIONS&;
v4 = &MAESTROMESSAGETYPE_GAMECLIENT_ENUMERATE_LATEST_VERSIONS&;
v4 = &MAESTROMESSAGETYPE_GAMECLIENT_INSTALLED_GAME_VERSION_SIZE&;
v4 = &MAESTROMESSAGETYPE_INVALID&;
sub_, a3, v4);
至此,可以看到lol launcher的协议指令类型都在这里。再看看哪里调用了Maestro_MessageTypeToString函数:
signed int __cdecl MaestroMessageAgent_SendMessage(int a1, int a2, const char *a3)
unsigned int v4; // [sp+24h] [bp-28Ch]@2
char v5; // [sp+28h] [bp-288h]@12
char v6; // [sp+168h] [bp-148h]@12
v4 = strlen(a3);
if ( !*(_DWORD *)(a1 + 16) )
Maestro_Log(2, &Cannot send messages when the MessageAgent isn't started.\n&);
sub_1001FE7A(*(_DWORD *)(a1 + 12));
if ( !sub_) || a3 && !sub_) )
sub_10027FBA();
sub_10027FBA();
if ( *(_DWORD *)(a1 + 36) == 1 || a2 != 4 && a2 != 5 )
Maestro_MessageTypeToString(a2, &v5, 0x140u);
sub_10027D05(&v6, 320, &SendMessage [%s]\n&, &v5);
Maestro_Log(0, &v6);
再看看 MaestroMessageAgent_SendMessage 的调用处:
signed int __cdecl MaestroGameController_SendGameConnectedToServerMessage()
if ( dword_ )
result = MaestroMessageAgent_SendMessage(**(_DWORD **)dword_, 10, NULL);
Maestro_Log(2, &MaestroGameControllerStruct is not yet initialized.\n&);
result = 0;
从 MaestroGameController_SendGameConnectedToServerMessage 函数名的字面含义上理解,此函数为『当游戏连接到服务器时,发送消息』,继续跟进…可是,我静态分析水平比较弱,越是继续跟进,我的思路越混乱,决定另辟蹊径。
在文中最初的LOL目录结构中,有个Logs目录,这个目录下Maestro Logs目录中的maestro-server.log、maestro-game_client.log中有一些日志,是开发人员用来排查调试程序执行结果的信息,大约如下:
INFO: maestro [server] initializing...
INFO: New thread go!
INFO: Starting Process Thread Spinning
INFO: Using registered HWND:
to launch the air client.
INFO: StartProcess [MAESTROPROCESSTYPE_AIR] successful
INFO: Launcher init of maestro completed.
INFO: ReceiveMessage [MAESTROMESSAGETYPE_GAMECLIENT_CREATE]
INFO: New thread go!
INFO: Starting Process Thread Spinning
INFO: StartProcess [MAESTROPROCESSTYPE_GAME] successful
INFO: ReceiveMessage [MAESTROMESSAGETYPE_GAMECLIENT_LAUNCHED]
INFO: SendMessage [MAESTROMESSAGETYPE_GAMECLIENT_LAUNCHED]
INFO: ReceiveMessage [MAESTROMESSAGETYPE_GAMECLIENT_CONNECTED_TO_SERVER]
INFO: SendMessage [MAESTROMESSAGETYPE_GAMECLIENT_CONNECTED_TO_SERVER]
INFO: ReceiveMessage [MAESTROMESSAGETYPE_CHATMESSAGE_FROM_GAME]
INFO: SendMessage [MAESTROMESSAGETYPE_CHATMESSAGE_FROM_GAME]
INFO: ReceiveMessage [MAESTROMESSAGETYPE_CHATMESSAGE_TO_GAME]
INFO: SendMessage [MAESTROMESSAGETYPE_CHATMESSAGE_TO_GAME]
INFO: ReceiveMessage [MAESTROMESSAGETYPE_CHATMESSAGE_TO_GAME]
INFO: SendMessage [MAESTROMESSAGETYPE_CHATMESSAGE_TO_GAME]
INFO: ReceiveMessage [MAESTROMESSAGETYPE_GAMECLIENT_ABANDONED]
INFO: SendMessage [MAESTROMESSAGETYPE_GAMECLIENT_ABANDONED]
INFO: [MaestroMessageAgent_ReadFromSocketInternal] 操作成功完成。
WARNING: Received 0 bytes on Maestro socket when data was expected.
INFO: ReceiveMessage [MAESTROMESSAGETYPE_CLOSE]
INFO: SendMessage [MAESTROMESSAGETYPE_CLOSE]
INFO: maestro exiting...
这里确实可以对应着launcher协议中,某些command被接收后,会被记录到这里。如何确认每个日志记录指令对应是哪个TCP包发送后的结果呢?如何利用这些日志信息呢?如果windows上有类似linux的strace查看系统调用的工具就好了,你还别说,还真有一款功能类似的,就是
好了, lol.launcher_tencent.exe 的功能大约理清楚了,再来回顾下League of Legends的客户端架构,以及猜测下服务端架构,根据我的理解,我画了一副图
League of Legend英雄联盟架构图猜测
架构图中的虚线部分,为服务器之间节点通讯,是我的猜测,并不是想客户端部分那样,按照分析客户端通讯得来的架构图。可能不准确。
匹配请求处理服务器,用来处理客户端的登录认证、符文、天赋修改、英雄列表,进入战斗的匹配请求等。
匹配服务器,应该是整个大区用同一个,这里会预算所有与大区玩家相关的数据,战斗力匹配,寻找想匹配对手,划分到对应服务器中。这是核心点,也是瓶颈点。
房间管理服务器,应该要独立拆分出来,与匹配服务器解耦,与战场服务器解耦。当匹配服务器完成后,只要将匹配结果的10名玩家,玩家的符文、天赋配置等发送给房间管理服务器,然后由房间管理服务器去创建对战进程,再获取对战服务器的IP PORT 以及每个人的加密KEY(也应该是认证该角色的凭证),比如 “14.17.23.94 5156 QbwA4soB8Jq7COEQ+1xc4g== ” 发送给每一个客户端。客户端拿到消息,再发送给lol.launcher.tencent.exe,再有它启动游戏进程。
房间管理服务器都是可以横向扩展的,尤其是游戏服务器,更是可以横向扩展,单个游戏进程,只跟本次游戏中的10个玩家有关。
port范围,也就是说单台服务器最多开500个端口,也就是500场战斗,以每场战斗10个人来算,单台服务器是5000人的承载。实际上可能要依赖服务器的性能承载。15年初网上消息LOL同时在线750W,时隔1年,国服现在同时在线有多少人?能承载多少玩家同时在线?匹配服务器虽然是很难拆分的节点,但业务比较单一,CPU密集型,应该大概也许可能不难解决。其他节点,拓展起来就更方便了,堆堆服务器应该可以解决。当然,我没坐过类似的客户端游戏架构,只是基于页游、手游的经验猜。
回到正题,LOL launcher的业务确定了,与另外两个进程通讯的协议格式也确定了,看看实现时,我要怎么做
监听系统信号的线程
监听TCP 8393端口,等待LolClient.exe连接
监听TCP 8394端口,等待League of legends.exe连接
监听TCP 8395端口?暂时不监听了,目前不知道这端口是干啥的
启动client的线程
保持与client的心跳线程
启动game的线程
保持跟game的心跳线程
接收来自game消息的心跳线程
处理client消息转发到game的线程
处理game消息转发到client的线程
解析协议数据包,获取command,数据包长度,数据包内容
type Header struct {
uint32 //默认0x10
uint32 //默认0x01
pCommand uint32 //默认0x00
uint32 //默认0x00
func (head *Header) Read(buf []byte) {
head.pHead0 = binary.LittleEndian.Uint32(buf[:4])
head.pHead1 = binary.LittleEndian.Uint32(buf[4:8])
head.pCommand = binary.LittleEndian.Uint32(buf[8:12])
head.pLength = binary.LittleEndian.Uint32(buf[12:16])
type LolLauncherPacket struct {
pHead Header
pData []byte
分析command,心跳包直接回复。与game无关消息包,直接回复MAESTROMESSAGETYPE_REPLY类型已收到该消息。
func (this *LolLauncherClientCallback) OnMessage(c *gotcp.Conn, p gotcp.Packet) bool {
packet := p.(*LolLauncherPacket)
data := packet.GetData()
commandType := packet.GetCommand()
switch commandType {
case MAESTROMESSAGETYPE_GAMECLIENT_CREATE:
// 0x00 存储data数据,此数据为League of legends 启动参数
c.AsyncWritePacket(NewLolLauncherPacket(MAESTROMESSAGETYPE_REPLY, []byte{}), 0)
log.Println(&LOGIN KEY:&, string(data))
////启动游戏进程
this.PacketSendChanToMain &- packet
case MAESTROMESSAGETYPE_CLOSE:
//0x03 游戏进程退出
this.PacketSendChanToMain &- packet
case MAESTROMESSAGETYPE_HEARTBEAT:
//0x04 回复收到心跳
c.AsyncWritePacket(NewLolLauncherPacket(MAESTROMESSAGETYPE_REPLY, []byte{}), 0)
case MAESTROMESSAGETYPE_REPLY:
//0x05 不处理(一般不会有这种消息)
case MAESTROMESSAGETYPE_CHATMESSAGE_TO_GAME:
//0x0b 来自游戏大厅的消息,需要转发至游戏进程
this.PacketSendChanToMain &- packet
//MAESTROMESSAGETYPE_INVALID
log.Println(&Client-&OnMessage-&MAESTROMESSAGETYPE_INVALID:&, commandType, & -- &, packet.pHead, & -- &, data)
部分消息需要转发给game进程,走chan转发,比如进入游戏后,好友还是可以在游戏大厅发消息到正在游戏中的玩家的,聊天消息转发MAESTROMESSAGETYPE_CHATMESSAGE_TO_GAME 就是从client发到launcher,再有launcher转发至game的。处理client消息转发到game的线程、处理game消息转发到client的线程
//监听客户端通道消息
go func() {
packet := &-clientPacketChan.packetSendChanToMain
data := packet.GetData()
commandType := packet.GetCommand()
switch commandType {
case proto.MAESTROMESSAGETYPE_GAMECLIENT_CREATE:
//获取参数,启动游戏进程
go lolCommands.LolGameCommand(strconv.Itoa(int(lolgame_port)), string(data))
//消息发送至game客户端
case proto.MAESTROMESSAGETYPE_CLOSE:
// 0X03 游戏关闭
case proto.MAESTROMESSAGETYPE_HEARTBEAT:
//0x04 回复收到心跳
case proto.MAESTROMESSAGETYPE_REPLY:
//0x05 确认收到消息包的回复(可以不做处理)
case proto.MAESTROMESSAGETYPE_CHATMESSAGE_TO_GAME:
//0x0b 来自游戏大厅的消息,需要转发至游戏进程(在ClientCallback中实现)
gamePacketChan.packetReceiveChanFromMain &- packet
//MAESTROMESSAGETYPE_INVALID
log.Println(&Client(main)-&OnMessageFromMain-&MAESTROMESSAGETYPE_INVALID:&, commandType, & -- &, packet.GetHeader(), & -- &, data)
当然,还得再启动两个线程来接收launcher转发来的消息,
func (this *LolLauncherClientCallback) OnMessageFromMain(c *gotcp.Conn) {
packet := &-this.PacketReceiveChanFromMain
data := packet.GetData()
commandType := packet.GetCommand()
switch commandType {
case MAESTROMESSAGETYPE_GAMECLIENT_ABANDONED:
c.AsyncWritePacket(packet, 0)
case MAESTROMESSAGETYPE_GAMECLIENT_LAUNCHED:
c.AsyncWritePacket(packet, 0)
case MAESTROMESSAGETYPE_GAMECLIENT_CONNECTED_TO_SERVER:
//0XOA 连接到服务器
c.AsyncWritePacket(packet, 0)
case MAESTROMESSAGETYPE_CHATMESSAGE_TO_GAME:
//0x0b 来自游戏大厅的消息,需要转发至游戏进程(在ClientCallback中实现)
c.AsyncWritePacket(packet, 0)
case MAESTROMESSAGETYPE_CHATMESSAGE_FROM_GAME:
c.AsyncWritePacket(packet, 0)
//MAESTROMESSAGETYPE_INVALID
log.Println(&Client-&OnMessageFromMain-&IGNOREMESSAGE:&, commandType, & -- &, packet.pHead, & -- &, data)
等等等等,一系列代码写完后,本以为终于可以在osx上玩LOL国服了,没想到,我还是太年轻,想的太简单了。程序启动LolClient.exe之后就假死了,一番排查后,发现是TCP粘包问题
LolClient.exe的TCP 粘包
LolClient.exe的TCP 粘包
尼玛,是LolClient.exe发送给launcher.exe的TCP数据包分了两个TCP包发送的,尼玛,100个字节都不到,还分两个字节,尼玛。。累不累?
一系列代码写完后,本以为终于可以在osx上玩LOL国服了,没想到,我还是太年轻,想的太简单了。我写的lol launcher启动Lolclient.exe没问题,符文、天赋编辑也都没问题。但启动League of legends.exe时,却进程崩溃退出了,而我却百思不得其解,为什么?通信协议一样的,发送command时机一样的,为什么会崩溃呢?这突然的失败,让我思路中断,思绪全无,不知道如何进行下去。。。。。。冥冥中,我记得在静态分析 lol.launcher.tencent.exe 时,看到了一个特殊的函数名
LOL进程启动的环境变量
再回到ProcessMonitor中看看League of legends.exe启动时的环境变量是什么
League of legends.exe的环境变量
__COMPAT_LAYER=ElevateCreateProcess (不要问为什么
…我也曾经懊恼过,上学时,老师总是说显然,可我就是不明白为什么
在OSX上,也找下环境变量是什么获取LeagueOfLegends.app进程执行时的环境变量,去除系统默认的几个,剩下的,就是游戏自己添加的
cfc4n@cnxct:~$ ps -ef|grep League
4:37下午 ??
0:00.55 /Applications/League of Legends.app/Contents/LoL/RADS/solutions/lol_game_client_sln/releases/0.0.0.193/deploy/LeagueOfLegends.app/Contents/MacOS/LeagueofLegends 8394 LoLPatcher /Applications/League of Legends.app/Contents/LoL/RADS/projects/lol_air_client/releases/0.0.0.210/deploy/bin/LolClient 182.162.122.113 5102 yvqljG4isLEGWoQS4WEEUA==
cfc4n@cnxct:~$ ps -wwE -p 3955
0:24.44 /Applications/League of Legends.app/Contents/LoL/RADS/solutions/lol_game_client_sln/releases/0.0.0.193/deploy/LeagueOfLegends.app/Contents/MacOS/LeagueofLegends 8394 LoLPatcher /Applications/League of Legends.app/Contents/LoL/RADS/projects/lol_air_client/releases/0.0.0.210/deploy/bin/LolClient 182.162.122.113 5102 yvqljG4isLEGWoQS4WEEUA==
LOGNAME=cfc4n SHELL=/bin/bash USER=cfc4n riot_launched=true SSH_AUTH_SOCK=/private/tmp/com.apple.launchd.8MjNgu5Xfd/Listeners XPC_SERVICE_NAME=com.riotgames.MacContainer.67552 HOME=/Users/cfc4n __CF_USER_TEXT_ENCODING=0x1F5:0x19:0x34 TMPDIR=/var/folders/dn/qvv6vmxd6c5g8bf6t0dtwwcw0000gn/T/ PATH=/usr/bin:/bin:/usr/sbin:/sbin Apple_PubSub_Socket_Render=/private/tmp/com.apple.launchd.ZBoYrDDTEF/Render XPC_FLAGS=0x0
//对其格式,如下
LOGNAME=cfc4n
SHELL=/bin/bash
USER=cfc4n riot
launched=true
SSH_AUTH_SOCK=/private/tmp/com.apple.launchd.8MjNgu5Xfd/Listeners
XPC_SERVICE_NAME=com.riotgames.MacContainer.67552
HOME=/Users/cfc4n
__CF_USER_TEXT_ENCODING=0x1F5:0x19:0x34
TMPDIR=/var/folders/dn/qvv6vmxd6c5g8bf6t0dtwwcw0000gn/T/
PATH=/usr/bin:/bin:/usr/sbin:/sbin
Apple_PubSub_Socket_Render=/private/tmp/com.apple.launchd.ZBoYrDDTEF/Render
XPC_FLAGS=0x0
func (this *launcher_commands) LolGameSetenv() {
var LolEnvKeys = [12]string{&LOGNAME&, &SHELL&, &USER&, &SSH_AUTH_SOCK&, &XPC_SERVICE_NAME&, &HOME&, &__CF_USER_TEXT_ENCODING&, &TMPDIR&, &PATH&, &Apple_PubSub_Socket_Render&, &XPC_FLAGS&, &riot_launched&}
var LolEnvs map[string]string
LolEnvs = make(map[string]string)
for _, v := range LolEnvKeys {
switch v {
case &riot_launched&:
LolEnvs[v] = &true&
case &XPC_SERVICE_NAME&:
LolEnvs[v] = &com.riotgames.MacContainer.67552&
LolEnvs[v] = os.Getenv(v)
os.Clearenv()
for k1, v1 := range LolEnvs {
os.Setenv(k1, v1)
一系列代码写完后,本以为终于可以在osx上玩LOL国服了,没想到,我还是太年轻,想的太简单了。除了程序执行时的环境变量外,还有一个程序执行时的当前目录:
cfc4n@cnxct:~$ ps -ef|grep League
4:34下午 ??
0:04.64 /Applications/League of Legends.app/Contents/LoL/RADS/system/UserKernel.app/Contents/MacOS/UserKernel updateandrun lol_launcher LoLLauncher.app
4:34下午 ??
0:00.32 /Applications/League of Legends.app/Contents/LoL/RADS/projects/lol_launcher/releases/0.0.0.170/deploy/LoLLauncher.app/Contents/MacOS/LoLLauncher
4:34下午 ??
0:00.24 /Applications/League of Legends.app/Contents/LoL/RADS/projects/lol_patcher/releases/0.0.0.42/deploy/LoLPatcher.app/Contents/MacOS/LoLPatcher
4:34下午 ??
0:02.26 /Applications/League of Legends.app/Contents/LoL/RADS/projects/lol_air_client/releases/0.0.0.210/deploy/bin/LolClient -runtime .\ -nodebug META-INF\AIR\application.xml .\ -- 8393
4:37下午 ??
0:00.55 /Applications/League of Legends.app/Contents/LoL/RADS/solutions/lol_game_client_sln/releases/0.0.0.193/deploy/LeagueOfLegends.app/Contents/MacOS/LeagueofLegends 8394 LoLPatcher /Applications/League of Legends.app/Contents/LoL/RADS/projects/lol_air_client/releases/0.0.0.210/deploy/bin/LolClient 182.162.122.113 5102 yvqljG4isLEGWoQS4WEEUA==
4:34下午 ttys000
0:00.00 grep League
cfc4n@cnxct:~$ lsof -a -d cwd -p 3828
TYPE DEVICE SIZE/OFF
UserKerne 3828 cfc4n
/Applications/League of Legends.app/Contents/LoL/RADS/projects/lol_launcher/releases/0.0.0.170/deploy
cfc4n@cnxct:~$ lsof -a -d cwd -p 3847
TYPE DEVICE SIZE/OFF
LoLLaunch 3847 cfc4n
/Applications/League of Legends.app/Contents/LoL/RADS/projects/lol_launcher/releases/0.0.0.170/deploy
cfc4n@cnxct:~$ lsof -a -d cwd -p 3848
TYPE DEVICE SIZE/OFF
LoLPatche 3848 cfc4n
/Applications/League of Legends.app/Contents/LoL/RADS/projects/lol_patcher/releases/0.0.0.42/deploy
cfc4n@cnxct:~$ lsof -a -d cwd -p 3871
TYPE DEVICE SIZE/OFF
LolClient 3871 cfc4n
/Applications/League of Legends.app/Contents/LoL/RADS/projects/lol_air_client/releases/0.0.0.210/deploy/bin
cfc4n@cnxct:~$ lsof -a -d cwd -p 3955
TYPE DEVICE SIZE/OFF
LeagueofL 3955 cfc4n
/Applications/League of Legends.app/Contents/LoL/RADS/solutions/lol_game_client_sln/releases/0.0.0.193/deploy
记得要chdir一下,这么改进后,本以为终于可以在osx上玩LOL国服了,没想到,它确实在windows上登录国服,终于运行起来了
自己写的lol launcher在windows上成功运行了
它也在OSX上登录美服,成功运行起来了
我自己写的lol launcher成功在OSX上运行了美服、韩服
那么我只要把OSX上启动LolClient的命令行参数改为国服的参数,就可以登录国服,玩国服游戏咯,尝试一下
LOL OSX登录国服
果然可以,我情不自禁的开始佩服我的聪慧,机智,下一步就开房间,匹配打国服了?然而,我还是太年轻,想的太简单了。程序启动League of Legend.app时出错了,进不去,日志中记录
0.0000kb added| ALWAYS| r3dRenderLayer::RecreateOwnedResources
0.0000kb added| ALWAYS| r3dRenderLayer::InitResources exit successfully
0.0000kb added| ALWAYS| Waiting for client ID
0.0000kb added| ALWAYS| {&messageType&:&riot__game_client__connection_info&,&message_body&:&Hard Connect&}
0.0000kb added| ALWAYS| Received client ID
0.0000kb added| ALWAYS| Set focus to app
0.0000kb added| ALWAYS| Input started
0.0000kb added| ALWAYS| Query Status Req started
0.0000kb added| ALWAYS| Query Status Req ended
0.0000kb added| ALWAYS| Waiting for server response...
之后,游戏进程就报错退出了。我太年轻了,想的太简单了……可是,我好像已经不年轻了……
这到底是为什么,玩个游戏怎么这么难,这么难?我只是想玩个游戏而已,为什么这么难? 腾讯LOL项目组的朋友,能不能告诉我,你们还验证了什么? 很明显不是版本号,是不是操作系统?是不是拒绝了OSX的登录? 曾经,我曾尝试过从协议上入手,看看LOL游戏协议能不能搞定,可难度比较大,花了好几个星期的空余时间,大约确认了是UDP Enet协议格式,后来,也在网上搜到相关信息,确认了。但网上公开的协议格式,是4.23以前的,现在都6.*的版本,早就改了….唉,以后再说吧…
最近两天,总结了之前研究LOL Launcher的实现过程,疏于工作,拖延了工作进度,我自己也是内心有愧。有愧的不仅仅是会议上的苍白答复,也还有这篇总结本计划与2015年底写完的,也还是拖延到现在。总结完这边博文,接下来要写部门的年终总结了,离丙申年到来还有5天,犯有严重拖延症的我,能把我自己的年终总结,在乙未年结束之前写完吗?
已发表评论数()
已收藏到推刊!
请填写推刊名
描述不能大于100个字符!
权限设置: 公开
仅自己可见
正文不准确
标题不准确
排版有问题
没有分页内容
图片无法显示
视频无法显示
与原文不一致

我要回帖

更多关于 英雄联盟死机问题 的文章

 

随机推荐