上一节我们使用了第三方天气预报接口,配合自己做的视窗界面,实现了一个相当不错的天气预报程序。现在回顾一下,天气预报小程序是怎样工作的。
TIPS:
时不时盘点一下成果,可以避免写代码真的成为 "搬砖"。
很多人对编程存在误解,以为编程就是噼里啪啦敲键盘。其实编程更像是写文章,写字本身不是重点(当然不会写也不行),头脑中的思想才是!
写代码的过程,只不过是实现头脑中的构思。每一个软件都是一个小型系统,通过复盘深入理解所有细枝末节,管理好有限的资源才是核心技能。
互联网时代,很多优秀的开发者,本身也是先进的管理者,也很容易理解了。
互联网的奇迹
现在很少有不联网的电脑,没有网络,计算机的价值要大打折扣。我们的天气预报小程序虽然很简单,但是不折不扣的互联网应用。
前面已经提到,本机运行的天气预报程序是客户端。无论多复杂的客户端,大体只负责两件事:
- 接受客户输入;
- 展示服务端的数据。
用户虽然可以利用天气预报程序得知天气预报,但是真正的天气数据收集、预测、发布工作,都是在服务端完成的,客户端只是展示而已。这种模式相比较以往所谓 “单机” 程序有深远的意义:
- 业务可以做的更大更复杂,但是却更廉价。现在的服务基本都在 “云” 上,国内常见的阿里云,国外有世界知名的亚马逊云服务。服务端拥有更好的硬件资源,提供更强大的性能,却对客户端机器没什么太多要求;服务端同时为很多人服务,对于客户来说,成本反而降低了,服务端数据相当于薄利多销。
- 极大保护知识产权。Python 程序属于脚本语言,我们的天气预报程序几乎无法对抗用户对它进行修改。由于真正的服务在服务端,天气数据也在服务端,用户对客户端的修改,对天气预报业务的损失非常小。如果有账号系统,极端情况下,我们让搞破坏的用户下线就好了。
- 软件运维方便。由于天气预报业务在服务端完成,如果我们采用了新的 “天气模型”,只要 “偷偷” 在服务端修改就好了,用户几乎察觉不到什么变化。特别是服务端程序故障端时候,可以直接登陆到自己到服务器上修复。在互联网兴起之前,一旦程序出现问题,就只能期待着用户会更新安装包。
TIPS
强烈推荐 《黑客与画家》—— Paul Graham,作者对软件工程、技术人员职业生涯有很不错的见解。
当然了,天气预报程序的天气预报服务不是我们做的,但是必须承认,它才是天气预报业务的核心。
在之前的项目中,我们利用 requests 库发起 HTTP 请求,从天气预报 web 接口获得天气预报数据。如果你还有印象的话,天气预报的数据是 Json 格式,一种非常像 Python 字典的数据格式。
服务端是如何提供服务端呢?大体步骤就 2 个:
- 接受请求
- 返回数据
再接受请求和返回数据之间,是服务端辛勤工作的时机,以便准备有用的信息给客户端 “返回”。
一图胜千言,仔细看一下客户端与服务端之间的交互过程。
TIPS
客户端与服务端的通信通常是基于请求——响应模式,称之为交互。
服务端的业务就发生在黄色部分,通常是一些访问数据库、数据整理的工作。
定睛一看服务端
客户端主要是获取数据,展示,非常简单,而且之前编写天气预报视窗程序的工作,都属于在客户端的努力。
我们在客户端已经投入了相当的精力,现在不妨仔细看看一下服务端是如何工作的,虽然不一定每个人都有必须自己写服务端,我的建议还是:知其所以然!
- 客户端如何找到服务端的机器?
互联网与电话网有很多相似性(实际上早期很多人用过电话拨号上网,互联网可以运行在电话网络上)。
首先看一下你家里的座机。
网络中的电话机千千万,电话是通过编号区别的。在互联网中,这个编号叫 IP 地址(IP address),通常简称 IP。
假设你家的电话号是 883454,这个号码是由运营商分配给你的。这个号码全市唯一,别人就不能再用这个号了。这样,所有人都可以用这个号码找到你(外市可能要加区号,暂时搁置这个问题好嘛)。在互联网中这样的号码叫 “公网地址”,是全球唯一的。
同时你家里有很多分机,它们需要一个你家里的唯一分机号,比如 01,02 等等。互联网中也有类似的情况,比如同一 Wifi 下的所有设备都会得到一个当前 Wifi 下的唯一 “分机号”,称之为 “局域网地址”。相对于公网,局域网也称为 “内网” 或者 “私网”。
注意,局域网地址只要保证在 “局部” 唯一就可以,比如你家的某个分机号为 01,别人家也可能会在自己家用分机号 01,互不干扰,各家是各家的事。“局域网” 的 “局域” 俩字儿就是这个意思,分机号只能保证在局部唯一。
因此:
- 同一内网所有 “分机“ 之间可以用局域网地址互相通信,
- 任意内网 ”分机“ 也可以向任意公网 IP 通信,
- 内网 ”分机“ 无法直接与其他局域网中的分机通信。
该说服务端了,服务端也是一样,也拥有自己的公网地址,而且它的内部也会有很多分机,拥有自己的局域网地址。比如上图展示的客服公司,拥有自己的电话号(公网地址) 和内网的一些分机。
TIPS
直接将计算机暴露在公网地址是很危险的行为,因为互联网实际上是对等的,任何拥有公网地址的计算机都可以接收、发送数据,换句话说任何公网下的计算机可以同时扮演 “客户端” 和 “服务端”。一旦你的计算机可以任由其他人连接,没有足够专业知识的情况下,很有可能被不怀好意的人攻击,造成损失。
好在大多数情况下,个人计算机得到的只是运营商自建局域网的 “分机号”,运营商只允许内部局域网的计算机作为客户端,极大的降低了个人计算机被主动攻击的可能行。倒也不是运营商热心,主要是服务器地址(公网地址)有经济价值,所以阉割掉了普通用户计算机对全球提供服务的能力。
如果希望局域网计算机对公网提供服务,可以了解 “内网穿透” 技术。
服务端会处理很多业务,就像一家公司可能有商务部、销售部、技术部。我们可以通过电话找到一家公司,还需要额外的信息指定要联系的具体业务部门,一种方式是公司为不同业务开不同的窗口,并编号。这样只需要通过 电话 + 窗口编号,就可以直接展开业务洽谈。
服务端采用类似的策略,不过这种窗口称为端口,以整数编号。比如天气预报的 HTTP 服务,使用的是 80 端口,客户端通过:
- 公网地址:端口号
直接找到天气预报数据服务。最终具体干活的是服务端内部的某个 “分机”,这样的细节对客户端就没什么意义了。
- 天气接口的组成
IP 是一组二进制数据,通常为了方便,将他们以 "." 分割为 4 个 0~255 的整数,比如百度的一个 IP 地址是:220.181.38.150。 百度的服务也是 HTTP 服务,我们就可以在浏览器中填写 220.181.38.150:80 访问百度主页。
不对啊,我记得天气预报的接口是:http://wthrcdn.etouch.cn/weather_mini,没有 IP 和 端口啊!
其实是有的,我们对天气预报接口进行分解,得到:
- 协议,确定数据组织格式。
- 域名,其实是为了解决 IP 地址难记的问题,baidu.com 就比 220.181.38.150 好记的多。有专门的服务(DNS)会自动将域名转换为 IP 地址。所以天气预报接口是有 IP 地址的,不过是隐含的。
- URL,定位了资源在服务上的位置,很像计算机上的分级目录。
- 端口,由于 80 端口是 HTTP 协议的默认端口,所以在接口中没有指明。你也可以用 wthrcdn.etouch.cn:80 替代 wthrcdn.etouch.cn,不会有任何影响。
再总结一下,服务端所需要的东西:
- 使用 HTTP 协议;
- 服务端有一个 IP,
- 指定一个端口,默认 80 端口;
- 就收请求,请求中包含 URL 信息,
- 准备一些数据
最终返回给客户端。
TIPS
一个特殊的地址:localhost 或者 127.0.0.1,是本机的 IP 地址。本机可以通过这个地址,自己与自己通信。
自己动手,丰衣足食
说了这么多,其实我就是想自己做一个服务端。
TIPS
用 Python 编程,一定要站在巨人的肩膀上。
今天的巨人是第三方库 bottle。这是一个非常轻量级的 web 框架,可以用来构建 http 服务。在这里查看它的文档。
从上一节开始,我们不再使用 online 环境,开始使用本地开发环境,毕竟本地方便的多。
首先在命令行安装 bottle:
pip install bottle
废话不多说,新建一个 bottle_demo 目录,在其中创建 main.py:
from bottle import route, run, template
@route('/hello/<name>')
def index(name):
return template('<b>Hello {{name}}</b>!', name=name)
run(host='localhost', port=8080)
快速运行第一个 web 程序
注意 run(host='localhost', port=8080),指定的就是 web 服务的 IP 地址和端口,localhost 表示在本机服务,port 的值是 8080,也就是这个小 web 服务在本机的 8080 端口工作。示意图如下:
然后打开浏览器,在地址栏输入:http://localhost:8080/hello/Jiangchuan,也可以用你的名字替换 Jiangchuan,就会看到第一个 web 服务运行起来了。
下面再仔细看一下地址栏中的信息与代码之间的关系。
由于代码中指定的端口是 8080,没有使用 HTTP 协议默认的 80 端口,所以在地址栏必须填写端口,不能省略。
如果希望改变 URL,就需要修改上图对应位置的代码,你可以试一试。
总结
复盘一下天气预报程序,服务端竟然才是核心,写了这么多,离实现天气预报服务还有很多事要做。
不过已经了解了 IP、域名、URL 之类的东西了,至少也运行起第一个 HTTP 服务实现 Say hi,也值得自己鼓励自己一下!
你要是问我,不是搞 PySimpleGUI 吗,搞什么 HTTP 服务呢?很快你会明白我的用心的。
明天继续咯。