telegram网络层源码分析如何阅读(Desktop)的源代码?-电报telegram技巧分享

telegram源码

近来看了一下Telegram网络层的源码,原来想网上找一下现成的结论,降低一点学习本钱,但是并没有发现相关的资料。于是自己梳理了一下telegram是怎样发送网络请求和相应回包的,这里做个总结。

连接的创建

先上一张图:

ConnectionsManager

这张图描述了telegram客户端和server的连接时怎样创建的。Java层的ConnectionsManager是一个线程安全的单例,实在只是个wrapper,真正的逻辑都是转交给C++层的ConnectionsManager类处置的。 C++层的ConnectionsManager对象,在

TgNetWrapper.cpp

中初始化,也同样是个单例。这里贴一下C++层ConnectionsManager类的init方法:

这里有两个重要的方法调用,一个是loadConfig(),一个是pthread_create()。顺着时间线往下看,loadConfig()调用了initDataCenter()方法,这个方法实现如下:

可以看到,重要是一些hardcode的IP和端口,实在在连接上第一个数据中心之后,客户端就会被分发到最优的数据中心接入,这里写这么多,可以看作一种fallback逻辑。

接下来使用了一个pthread_create的调用,新的线程中会实行ThreadProc()方法,这个方法会先调用sendPing(),实现如下:

这里调用了DataCenter的getPushConnection()和getGenericConnection()方法,这里把connection种类区离开的本意是下载,推送等使用差别的连接,这样可以防备一些耗时使命不停占用连接,同一个数据中心,可以给差别种类的连接分派差别的IP和端口,来进步网络连接的服从。

接下来是一个循环,循环中不停调用select()方法,来处置请求,这个方法的实现如下:

这里有一个epoll_wait()的调用,直觉上来说,这就是处置网络请求的焦点,以是我们也从这里开始分析,先看一下这个

epolFd

上注册的fd:

这里分析一下,

epolFd

上注册的fd一共有两类:

  1. socket。这里可以看到,socket连接在创建时,会向epoll注册自己,在封闭时会把自己从epoll的监视列表移除。而adjustWriteOp()方法是在socket发送数据时调用,我们知道,对于socket的send,只是把数据发送到了缓冲区,假如缓冲区满会触发

    EAGAIN

    ,这个时间就要监听

    EPOLLOUT

    ,表现缓冲区可写,adjustWriteOp()方法完成的就是这个操作。
  2. 用于事件通知的fd,这里有

    eventFd



    pipeFd

    。这两个用于事件通知的fd不会同时使用,先初始化eventFd,pipeFd仅仅是在eventFd无法成功初始化时的备选方案。这两个fd详细用在那里可以看下面的代码段。

wakeup()方法调用的地方在这里:

这个scheduleTask()方法是写得最耐人寻味的地方。我原来以为,这只是个网络请求的使命队列,后来查了一下这个方法的调用,发现这个队列的工具真是应有尽有,什么加载文件,加载设置,设置dns,设置语言等使命都放到了这个队列里,感觉上是一个jni层全局的调理器。而对于网络请求,都是放在

requestQueue

中,察看sendRequest()方法不丢脸出来,处置网络请求是在processRequestQueue()方法中进行的。

如今再来看select()方法,流程就清晰多了,epoll_wait会在以下几种环境下被叫醒:

  1. socket连接有数据需要吸收
  2. socket缓冲区可写,上一次发送的数据没有完成
  3. 有使命在

    pendingTasks

    队列中

当线程被叫醒,不再壅闭之后,会首先行止理pendingTasks队列中的请求。然后调用epoll返回的EventObject对象的onEvent()方法依次处置,这个EventObject方法实在可以看作一个wrapper,会根据EventObjectType把逻辑分发到各个对象上,代码如下:

对于epoll,会用到的种类是EventObjectTypeConnection, EventObjectTypePipe, EventObjectTypeEvent.

完成EventObject的处置之后,接下来会封闭超时连接,这里的超时时间是12秒,然后要处置长连接的心跳。这里对于长连接心跳的处置如下:

  1. 封闭超时的长连接。这里对于超时的判断有两个条件,一是发送心跳包没有收到回包,已经已往了30s,二是间隔前次发送心跳包时间已经过了190s。
  2. 判定当前时间间隔上一次发送心跳包是否已经超越了180s,假如是的话,则发送长连接心跳包。这里可以得出结论,

    Telegram的长连接心跳周期是3分钟



    接下的处置非常良知,Telegram在检测到当前队列没有上传下载使命!和向server请求盐值的使命时,会封闭和数据中心的socket连接。这里有一个阈值是10s,可以以为,假如把应用切到后台,在完成当前队列里的上传和下载请求10s后,Telegram就会封闭长连接,停止发心跳。这个操作非常省电,反观国内大把app,种种黑科技保活。

    那么有一个问题,Telegram是怎样保证休眠后还能吸收到消息呢?答案是GCM,从AndroidManifest.xml里很轻易找到GCM对应service的实现类:

这里的ConnectionsManager.getInstance().resumeNetworkMaybe()就是实验重新恢复长连接的操作,逻辑很easy,就不再赘述。

最后一步,对于和DataCenter的普通连接,也发送心跳保活,这里的心跳周期是19s,然后每小时更新一次DataCenter的设置。再调用processRequestQueue()方法开始处置请求队列中的使命。

这里整理了一个比较直观的流程图,说明了发起请求的過逞。

select

Telegram网络模块的分析就到这里了。

编译的问题

前面一篇文章 Telegram-iOS github 拉取失败解决過逞 我们介绍了怎样从github上面拉取Telegram-iOS的源码,在文章的末端我说会介绍下怎样能将项目跑起来,这里兑现我的答应。

刚开始我也是根据官方的文档,拉代替码,留意肯定要拉取子模块,纵然用


git clone —recursive


下令,这样才能保证项目标完备性,在第五步中,让我们


Open the Telegram-iOS-Fork scheme.


我也根据这个步骤选中了这个scheme.

关于什么是scheme,我想搞iOS开发肯定知道这个,可以明白成一个编译计划,编译哪个target,怎么编译,环境变量是哪些。scheme可以选择属于project还是workspace。一个scheme对应一个target,一个target可以对应多个scheme。详细可以看 苹果官方文档

空话不多说,当我根据这个步骤拉代替码后,并选中 Telegram-iOS-Fork这个scheme后,装备选中模仿器编译,还是报错了,保持信息如下


No such module ‘SwiftSignalKit’ in TelegramAudio Framework


但是我看了,在 Linked Frameworks and Libraries中已经定义过了。

在github Issues中我找到了同样的问题

Unable to compile · Issue #82 · TelegramMessenger/Telegram-iOS · GitHub

看答复也是说选这个scheme,但是我这边还是报错了,答复中有一说是重复的问题

release-5.8 WatchCommonWatch/WatchCommonWatch.h not found · Issue #76 · TelegramMessenger/Telegram-iOS · GitHub

这里有个答复说用AppStoreLLC scheme 可以编译成功,我就试了下,果真通过了。

比我想象中要顺遂得多,至于详细什么缘故我还没去穷究,应该是工程设置的问题。背面再去查下,有知道的同窗欢迎留言。

碰到问题,我们多去看官方的一些Issue,你碰到的大概别人早已经碰到并解决过了。

源码分析-项目架构

好了顺遂跑起来工程后,我开始分析它的源码,Swift项目比 Objective-C项目 GitHub – peter-iakovlev/Telegram: Telegram Messenger for iOS )要清楚得多,作者都是peter-iakovlev。我们从提交记载就可以大抵看出,我们也能从两个项目中感觉到作者通过这个项目标进步。

这里我以一张图来简单介绍下项目标架构:

这里颜色上做个说明,绿色是swift语言,棕黄色是OC语言实现,白色是C和C++实现。可以大抵有个印象。这里有组件化的头脑,大抵看了下UI的实现,许多地方都是用facebook的UI框架AsyncDisplayKit来进步界面的流畅性,对于异步事件,用SSigalKit来处置信号。

业务层

在业务层,把UI和逻辑处置抽脱离来形成了TelegramUI 和 Telegram-iOS这两个组件。

协议层

在协议层,用了自家非常安全的MTProtoKit协议,已经对TL语言的swift实现TelegramApi,可以或许自己定义一套数据的表达语言,在多端同步使用,足以见起逼格。关于MTProto协议,我背面会专门花一篇文章来分析介绍。现在肯定有一个大抵的理解。

底子组件层

在底子组件层,作者也是展示了自己的架构本领,把每一个功能模块独立出来,特殊需要夸大的是TelegramCore这个库,从定名就能感觉到他的重要性,作为焦点支持库,背面我们也会来进行具体分析。在底子组件库中,有一个故意思的LegacyComponents库。内里的应该是OC项目遗留下来的,将来得及重构的组件,这里也可以看到一个软件开发的過逞。任何一个牛逼的开源软件都是这样不停的重构和迭代来的。

三方组件

在第三库上,作者用得还算比较克制,没有过多的用第三方库,都是业界非常闻名的开源库。

总结

通过这两天对源码的分析,我收获了许多,也对之前的自己的一些架构有所反思。写文章我们也可以用这样的头脑,小步迭代,逐步美满。

建了一个Telegram-iOS Swift版本的QQ学习讨论群,有爱好的可以参加

QQ群号:891790442


阅读代码是一个很大的话题。我简单的说说吧。

阅读代码实际上是编写代码的反向過逞,那么我们首先要搞清晰编写代码需要做哪些工作。

编写代码,我们首先要确定系统的框架。这个系统是单线程的,还是多线程的?是线性处置的,还是事件触发的?一样平常来说,我们会使用要么开发一个应用框架!来处置这个层面的工作。在建立了框架之后,后续的代码就需要遵照框架的限定和要求进行编写。

确定了框架之后,我们需要编写业务逻辑。这时间需要的是对业务需求的明白。

我们另有大概需要处置一些技能细节问题。技能细节一样平常会被封装到框架开发的阶段,但不清除在业务处置阶段也需要处置一些技能细节。

然后你需要做容错和不同寻常处置。实际中的不同寻常大概非常多,你需要对每一种不同寻常都给出对应的处置方法。

最后大概需要做一些优化的工作,为了提高性能,有大概需要使用一些非常本领,优化通常会粉碎代码的可读性。

在编写代码时,这些工作很大概不是一个人完成的。有些人负责框架,有些人负责业务逻辑,有些人负责技能细节,有些人负责优化。

而在读代码的时间,你看到的是一份巨细靡遗的工具,不会有人很清楚的区分出:这里是框架,这里是技能细节,这里是不同寻常处置,这里是优化……

以是,阅读代码的第一步,就是要把这些部分反向拆分出来。

首先你要知道这个系统使用了什么框架,你还得去认识这个框架的使用。假如使用的是通用框架,问题会简单些,通常可以找到对应的资料。假如是专用框架,那么你最好祷告有对应的文档,可以通过阅读文档对整体架构做明白,这样看详细代码会轻易的多。假如没有文档,那么最好能找到人问。假如这些都没有,那就就需要你有肯定的功底了。一样平常来说,框架层面的技能就那么几种,你首先要对这些技能有充足的理解。好比网络开发,你得知道Proactor、Reactor、Actor之类的常见模型,并知道他们的工作原理。这样你就可以通过一些粗读来判定!一个网络框架用了哪种模型,然后你就可以知道这个框架里的各个部分在做什么事了。然后渐渐深入,就可以逐步的分析出整个框架的完备面目。

然后可以开始阅读业务逻辑。这时间需要你对业务比较理解。你得知道一件事大抵是怎么做的。然后通过阅读代码来验证要么否认要么美满自己的想法。在业务代码中大概还会充斥着种种细节和不同寻常处置。你需要把这些抽丝拨茧的分散出来。要留意的是,在实际中,尤其是一些事件回调机制的系统中,业务逻辑有大概不是一跟到底的,而是疏散在很多差别的事件处置中,这种代码你得先理清晰事件的触发次序,然后才能理清业务。

最后是优化部分,这种假如你不是真的需要穷究,一样平常可以跳过。通常比较好的源码,优化都市有比较精良的封装和解释,不应该对正常的阅读产生太大的拦阻。

基本上来说,假如你对一份代码一无所知,是没法阅读的。阅读的条件是你知道许多配景知识,然后自己假设自己大概会怎么写,然后通过阅读代码来验证罢了。假如有文档的话要多加使用,对系统有整体明白后再深入进去会更轻易。

固然,阅读代码通常也是有目标的,你是想理解整个系统的总体运作机制?还是需要去改一个bug?要么想为他加强功能?根据目标的差别,可以从差别的条理开始,直接定位到自己的需求,而无需一开始就对整个代码洞若观火。这实在是一个很好的阅读切入点,比平常而读通常希望更快。

别的,偶然的也会碰到一些糟糕的代码,框架和业务糅合,随处布满了细节,整体逻辑切割得七零八落。这样的代码,我一样平常就直接放弃阅读了。

本文网址:

http://www.1cm8858.com/d/2020615102730_8071_444149602/home

Ten articles before and after

教你玩转电报(telegram)怎么玩-电报telegram技巧分享

俄罗斯解封聊天软件telegram币圈最火经历了什么?-电报telegram技巧分享

福建福州修车资源Channelstatistics北京.TelegramAnalytics-电报telegram技巧分享

工具教程第三十一讲:电报的使用(二)TelegramPC最新版支持移动端扫码登陆-电报telegram技巧分享

韩国n号房创始人身份被保护众多女艺人声明请愿公开-电报telegram技巧分享

安卓版whatsapp、telegram聊天文件可被黑客篡改妳的软件会监控吗?-电报telegram技巧分享

电报群组广播成都群-电报telegram技巧分享

为TelegramDesktop替换字体-电报telegram技巧分享

网爆5亿微博数据泄露GitHub-电报telegram技巧分享

使用telegram收发微信消息利用EFB2.0使·Forme-电报telegram技巧分享