标签归档:给产品经理讲技术

说说下载劫持那些事儿

本文转载自「给产品经理讲技术」公号,已经过原作者授权转载。

今年的双十一,想必广大千手观音们又狠狠的剁了几只手。然而,剁手换来的宝贝在漫漫快递路上也是命途多舛,轻者磕磕碰碰包装损毁,重者与快递货车一起被付之一炬。这些“不可抗力”造成的问题屡见不鲜,碰到了也只能自认倒霉。不过,有的网友看着苹果6代的订单,却啃着寄过来的6袋苹果,个中滋味大家就自行脑补吧…。其实,在安卓应用分发领域,这种“苹果6代”变“6袋苹果”的情况也屡见不鲜:

为什么会出现这种情况呢?其实一次网络下载的过程,就像一次“网购”,当我们点击下载按钮时,就跟下载服务器下了一份“订单”,“订购”了一个文件(当然大部分是免费的),服务器确认“订单”后,就会将文件在网络中“快递”(传输)到用户的终端(手机、PC等)。下载劫持一般出现在“下订单”的过程中。

举个栗子,假设我们通过微信官网的链接http://dldir1.qq.com/weixin/android/weixin637android660.apk下载微信安卓版本的客户端,整个流程大概是这个样子:

当点击了下载按钮后,客户端会通过url中的“域名”“dldir1.qq.com”来向DNS服务器获取确认“订单(下载)服务器”的IP地址,IP地址在互联网中相当于日常生活中“电话号码”,有了它,就可以连接到这台“订单(下载)服务器”,而DNS服务器就像一个存贮着大量“姓名”(域名)和“电话号码”(IP地址)的黄页。

当客户端获得了“订单(下载)服务器”的“电话号码”(ip地址)后,就会连接“订单(下载)服务器”,并告知“订单(下载)服务器”客户端需要获取服务器上的“微信安卓版”apk文件,一般情况下,服务器在这个阶段确认了“订单”后,就会向客户端“快递”(传输)对应的apk文件,当客户端将文件下载完毕后,这次“网购”也就完成了。

下面,我们引入运营商(电信、联通等)网关的概念。运营商网关可以类比成日常生活中的“总机”,接入运营商的互联网设备想要能够“上网”,都需要经过“总机”(运营商网关)的转接。也就是说,在上图中的第二步,我们并不能直接通过“订单(下载)服务器”的“电话号码”(IP地址)联系到“订单(下载)服务器”,而是需要先连接到“总机”(网关),并且告诉它,我们要向某某某服务器下“订单”,经过“总机”的转接,我们才能真正连接到“订单(下载)服务器”。整个过程如下图:

可以发现,DNS服务器和网关的决策,确定了客户端“订单”(下载请求)的走向。而“下载劫持”也就发生在这两个关键节点上。

假设客户端获取下载服务器“电话号码”的DNS服务器被篡改,那么客户端可能会通过“dldir1.qq.com”查询到一个“骗子服务器”的“电话号码”(IP地址),当我们联系到这个“骗子服务器”时,我们的“订单”(下载请求)可能会换来一些奇奇怪怪的“商品”。


当我们遇到这种情况时,可以手动修改DNS服务器IP(具体方法请问度娘)来解决。然而当运营商的“总机”(网关)“出了问题”(这些“问题”一般是运营商主动造成的)时,就没那么容易解决了。

假设当客户端拿着“订单(下载)服务器”的电话号码要求“总机”(网关)转接到我们指定的“订单(下载)服务器”时,“总机”(网关)对客户端说“哎呀,不要去A家下载微信了,你去我给你介绍的B家下载“XX助手”吧,比微信好用”(这个过程在技术上是被一个叫做302跳转的机制完成的,如果你不知道什么是302,出门左转,查询我们星期一的文章)。客户端是个实在人,就这样被“引诱”到B家的服务器上下载了。

“总机”(网关)和服务器B就这样沆瀣一气,来骗客户端的下载量。

刚刚给大家从技术层面简单介绍了下“下载劫持”的“饭醉手段”,至于为什么有人要做“下载劫持”,想必产品同学们应该比我更能知晓其中的奥妙,我就不班门弄斧了。就写到这里吧,我去洗水果了,双十一寄来的六袋苹果,再不吃就烂了….

(文中“XX助手”和服务器IP地址均属臆造,如有雷同,我也不知道是咋回事儿)

原文链接:点击查看

APP的推送是咋回事

本文转载自「给产品经理讲技术」公号,已经过原作者授权转载。

相信大家对推送这项技术并不陌生。如果没听说过,那么作为一个充满好奇心的孩子,你一定想过这个问题:睡觉前我明明关闭了淘宝、网易新闻等app,为什么第二天他们又自动出现在我手机的通知栏上呢?这其实就是推送系统干的好事:在你睡觉的时候,服务器悄悄的向你的手机推送了一个消息,然后唤醒了你已经关闭的app。事实上,无论你愿意与否,现在大多数‘有节操’的app,都已经内置了推送系统,并时刻准备着登上你的通知栏的‘头条’。

传统的app架构里,通常是app主动向服务器请求数据,服务器被动的提供数据。以新闻客户端app为例:app被用户打开的时候,会通过网络(无论3g、4g还是wifi)连接到服务器上,向服务器请求最新的新闻。服务器收到请求,从自己的数据库里查询最新的新闻,返回给app。app收到服务器返回的数据,经过一系列的解析处理操作,最终把最新的新闻呈现给用户。一次通信就完成了。然而如果此时服务器上又有了新的新闻,无论多么重要,在用户没有主动刷新的情况下,是没有办法让用户看到的。推送就是为了解决这样的困境的,它给了服务器一个展示自我的机会,主动连接上所有的app,告诉他们我有新的新闻了,你们再来请求一次吧,于是收到推送的app(即时此时已经被用户关闭了)又去服务器请求最新的新闻,这样用户就能看到最新的新闻了。

从技术上来讲,实现一个推送系统需要服务器端和终端的配合。一种方法是轮询,也就是不停的向服务器发起请求。这其实很好理解,作为app,我既然不知道什么时候会发生新的新闻,那我一遍一遍的问好了,而且我知道这样一定会成功的。显而易见,这种方法app端费时费力不说,电量流量也扛不住啊,服务器要处理如此量大的请求,必然也是非常头疼的。另一种方法是服务器和app建立一个长时间连接的通道,通过这个通道,不仅app可以向服务器请求数据,服务器也可以向app发送数据,看起来非常完美,但是如果app被用户关闭的话,通道就断掉了。好在android系统给app提供了一个这样的环境,app可以启动一个后台服务来维持这个通道,即使app被关掉了,服务依然可以运行,通道依然还在工作(ios后面会讲)。回到前面的例子,你在睡觉前关掉了淘宝,但是并没有关闭淘宝的后台服务,淘宝依然可以接收服务器推送来的指令,把自己的唤醒。

那么如何维持这样的一条长时间连接的通道呢?就好比两个人打电话,一开始聊的热情有来有往,后来慢慢沉默下来了,几分钟之后,电话的另一头没有任何动静,如何知道那边的人还在呢?很简单,只需要另一头的人每隔几分钟说一个字就行。同样的道理,app会每隔一段时间向服务器报告自己还活着,就像心跳一样,服务器收到后,就知道这个通道是可以继续使用的了。然而天下没有免费的午餐,发送心跳是有代价的,一般手机锁屏之后,为了省电CPU是出于休眠状态的,然而发送心跳就会唤醒CPU,必然会增加电量的消耗。这还只是一个长连接通道的情况,如果手机里装了2、30个带有推送的app呢?先别急着抱怨,聪明的android工程师和ios工程师早就想到了这一点,他们分别设计了GCM和apns来解决多个app有多个长连接通道的问题。以apns为例,ios开通了一条系统级别的长连接通道,通道的一端是手机的所有app,另一端是苹果的服务器。app的服务器如果有新的消息需要推送的话,先把消息发送到苹果的服务器上,再利用苹果的服务器通过长连接通道发送到用户手机,然后通知具体的app。这样就做到了即使手机安装了100个app,也只需要向一条通道里发送心跳。

回到Android,系统提供的GCM只能在Android2.2以上才能使用,3.0以下必须要安装Googleplay并登陆了Google账号才能支持。而国内发行的手机大多是阉割掉了google 服务的。因此,对于Android系统来说,各家app只能各显神通,开发自己的专用长连接通道了。然而这时候他们遇到了app的天敌:管家和卫士们。前文说了,app想要及时收到服务器推送的消息,关键在于自己与服务器的长连接通道不被关闭,也就是自己的后台服务可以一直在后台运行,而管家和卫士们的一键清理功能就是专治这种“毒瘤”的。道高一尺魔高一丈,app在与管家和斗士们的长期斗争中,总结了一系列躲避被清理掉的方法,什么定时自启能力、什么相互唤醒、什么前台进程等等,当然这就是另一个话题了,我们后面会讲到。

总结起来,app和后台的连接方式有两种。一种叫pull,也叫轮询,就是定期的不断向后台请求,缺点是耗电,费流量,不环保。对于一名有追求的程序员,他应该会比较恶心这种方式的,你千万不要对他说,我不管你怎么实现,我就要这种效果这种傻逼话了,凡事应该找到最优路径。另一种叫push,app和后台一直维持了一条通信通道,两端不定期的就会偷摸的约会,告诉对方“I‘m Here”,也能顺带把信息互相携带了。缺点是要维持一条长连接通道,这条通道容易被其他程序杀死,要多想复活办法。

原文链接,点击查看

前端和后台的数据交互与协议

本文转载自「给产品经理讲技术」公号,已经过原作者授权转载。

目前,除了一些特别简单非联网类应用(比如计算器、闹钟等),几乎所有的应用均是联网应用(比如新闻客户端,微信等等),这些app客户端基本都只是负责用户的交互与数据收集与展示,真正的数据和服务均存储在云端。

那移动端究竟如何和后台来交换数据并展示呢?我们打个比喻,其实整个过程跟去烧烤店儿撸串一样一样的。

拿任意一个新闻客户端举例,当用户刷新的那一刻(你萌生了吃烧烤的想法),客户端开始组织数据请求(你开始穿衣洗脸打扮,并思考该去哪一家吃呢),当用户界面开始展示loading的时候(这个时候你正走在“马大姐烧烤店”的路上),经过几百毫秒的时间,这个时候请求数据已经到了服务器(你已经坐在了马大姐烧烤店的桌子上),服务器开始查看客户端想要请求哪方面的数据,是请求财经频道的,还是请求汽车频道的数据(服务员递来了菜单,问你想吃啥),服务器看懂了客户端的想法开始准备数据(你点了20个肉串,10个大腰子),服务器看到你请求的是汽车频道和财经频道的数据(光着膀子的烤串师傅开始烤这20个串和10个大腰子),并给回到服务员,服务员一路小跑,将你要的串和腰子递到你的面前,这个时候相当于数据已经传回到了客户端,客户端loading消失,你看到了最新的两个频道的数据。

那客户端和服务器之间传输数据的格式是怎么样的呢?

现在流行的做法通常有两种,一种是类似于PB(Protocol Buffer,Google定义的一个数据传输协议,以简洁,省流,易用出名)的二进制数据(二进制数据的意思就是你打开这个文件你只能看到0和1组成的数字串,是没办法和你生活中任何认识的字母联系在一起的)传输,这种格式的好处是包小,重复的字段会被节省。另一种是JSON(JavaScriptObject Notation),这也是一种轻量级的数据传输格式,就是用一堆中括号把数据组织起来,不像二进制,这种格式是人可读的,并且比较轻巧,所以也有大量的应用场景。下面这段数据就是JSON格式,简单解读一下,就是people对应了三个人,三个人分别是中括号间的三个花括号中的人。

总结起来,十分简单,移动端提出需求,服务器按要求组织好数据发给你,针对不同的格式,移动端自己解析,展示,完活儿。其实,不止移动端,前端网页和后台,后台和后台之间也是这个道理。至于在传输的过程中都经历了什么,我们找机会再细聊。

原文链接:点击查看

网页与原生App如何交互

本文转载自「给产品经理讲技术」公号,已经过原作者授权转载。

想想平时用的App,你非常确信在浏览一个网页,然而需要登录时,它却唤起了你手机里的QQ或是微信,你不再需要输入帐号和密码就可以让你浏览的网页获取你的登录信息,这一切只发生在你指尖的两次点击。而在手机上,网页越来越炫酷,你都很难区分你在点击的是一个原生界面(指Native应用程序,说人话就是android app或ios应用)或仅仅是一个H5页面。你的操作一直穿梭在网页与原生界面之间,比如一个网页中的电话号码,点击就可以拨打电话,这种网页和app交互这一切是如何实现的呢?

这项能力在安卓中叫做Js2Java(ios上也提供类似的技术),很好理解,从Js到Java,从网页到app,他们是双向通信,可互相调用的,市面上大量的App程序,都在利用这项技术,微信更是本质上利用这项技术打造了公众帐号整个体系,使得创业者用一个简简单单的网页就打通了帐号、身份、支付、客服、售后等一系列操作,虽然简单,但是真的将移动互联网的Web生态囊括了更广阔的内容,也是移动互联网较PC互联网更优越、更猛烈的点之一。

以Android系统为例,Android手机上的App是使用Java语言编写的,而网页中则运行着一些Html、Javascript编写的代码,虽然Java和Javascript名字看起来像亲哥俩,但它们其实没有一毛钱关系,一个是编译型语言,一个是解释性语言,不多扩展,说不上哪天我就会写写编译型和解释性语言的区别。Android的App是通过WebView(请亲理解成一个组件,想象WebView就是一个没有任何操作按钮的浏览器,你输入baidu.com他就打开了百度的页面)来展示一个网页的,同时WebView为网页和原生App建立一个桥梁,让网页和原生App能够看到彼此暴露的一些方法,从而达到互相操作的目的。

当然,这些操作是需要前端页面和终端程序互相协商的。虽然很多App遵守了一些相同的原则,使网页在不同的APP中都能具备相同的能力,但是如果你看到同一个网页在一个App中能够调用一些安卓系统的能力,而在另一个APP中却没有对应的能力也不要觉得奇怪(找对应App的开发勾兑一下就好了)。

一个原生应用为网页开放的能力越多,网页对原生系统的操作能力就越强,就越能做出逼近原生应用的体验。但是,这却是一把双刃剑,因为原生App开放的能力有可能会被恶意的页面利用,对用户造成伤害,如何控制能力的开放,也是需要产品和开发一起思考的问题。例如微信是一个终端能力的宿主,拥有支付,登录,分享,获取App信息等能力,并以Js接口的形式提供给前端页面使用,前端开发则需要在微信申请对应的Js接口使用权限,才能够在微信中正常使用对应的能力。

最后总结一下,网页塑造界面的优势在于灵活,随时可以更新,而原生APP塑造的界面则能够提供更流畅的用户体验,但是却无法热更新,只能依靠发布版本来提供新功能。通过上面说的这种技术,就可以利用各自的优势,规避各自的劣势来提供更好用户体验,例如在微信中购物的展示是网页形式的,方便运营快速更新,通过Js接口调用起原生的支付界面,给用户更流畅的支付体验,提高支付成功率。

原文链接:点击查看。

关于给产品经理讲技术

一直以来,关于产品经理是否需要懂技术的话题就没有间断过。

产品经理不懂技术,需求异想天开,技术会认为产品经理瞎指挥不靠谱;

产品经理懂技术,需求太现实,实现上甚至都直接打技术的脸,技术会认为产品经理约越过了自己的边界里来…

实际上,产品经理不需要懂技术实现的细节,但是,应该懂一些技术原理的。

所以我就特别的想在我的公众号里能有一些关于产品经理需要知晓的浅显的技术原理的文章。

偶然间看到了「给产品经理讲技术」这个微信公号,关于技术的部分写的浅显易懂,言简意赅,确实很赞。

于是,跟公号作者商量,经过授权,可以将他的全部文章转载到我的公号上来。

他只要继续更新,我都会在读完之后挑选我认为很不错的文章选出来给大家看。

每篇文章的末尾,原文链接我都会尝试放原作者的公众号链接,大家可以在那里关注他的全部内容。

当然,除了懂技术,产品经理还需要懂点运营、懂点营销、懂点情趣。如果你正在用心的写,我也同样可以利用我的公众号,帮助你做宣传,只要你的内容足够的好。

绵薄之力,愿产品经理们能获得更多对自己有用的内容。