9.1. 为什么需要网络¶
硬件控制为摄像头提供了与某根特定线缆上某个特定设备通信的方式。摄像头与单块配套电路板之间的 UART。摄像头与挂在同一条短总线上的传感器之间的 I2C。共享一条稳健总线的一小组模块之间的 CAN。每种情况都遵循相同的模式:两方(或一个已知的小群体)、一个共享介质,以及双方之间关于该介质上字节含义的约定。
9.1.1. 这种模式无法扩展¶
只要两端都相距很近、两端都事先已知,并且脚本能够选择它要通过哪根线缆通信,点对点模式就能正常工作。一旦这些约束中的任何一个被打破,线缆连接就不再够用了。
对端数量众多。 五十台摄像头向一台服务器汇报的网络无法一对一接线;服务器上没有足够的 UART,而且布线长度也不可能实现。
对端不在同一根线缆上。 工厂里的一台摄像头和城市另一头办公室里的一个仪表盘无法共享一根串行线缆。必须通过两栋楼之间已有的某种基础设施在它们之间建立某条路径。
对端事先未知。 一台将结果发布到云端的摄像头并不会在接线图中选定它要与哪台服务器通信;云端的地址是脚本在运行时查询并将数据路由过去的。
一根线缆上有多个程序。 如今的一台笔记本电脑会同时运行浏览器、聊天应用、视频通话和备份程序,它们全都同时通过同一个网络接口通信。线缆无法像 UART 那样被某一次会话“独占”。
上述每一种失效都是一种不同类型的寻址问题。要把它们一并解决,所需的远不止一根线缆和一个波特率。
9.1.2. 网络是什么¶
网络是一种基础设施,它让大量计算机中的任意一台都能与任意另一台交换消息,而无需每一对之间都建立各自的专用连接。有三个特性使网络比一根大号串行线缆更胜一筹:
共享介质。 许多设备连接到同一根线缆、同一台交换机或同一个无线电信道上。它们轮流使用或进行多路复用,以便同一条物理链路上能容纳不止一次会话。
逻辑地址。 每个设备都有一个号码,用以标识它而不依赖于它插在哪根线缆上。发送消息意味着在消息上写下那个号码,而不是连接某根特定的线缆。
路由。 当发送方和接收方不在同一本地网段上时,位于它们之间的基础设施会逐跳传递消息。两个端点并不知道路由;它们只知道彼此的地址。
办公室 Wi-Fi 上的一台笔记本电脑访问远处数据中心的一台服务器,会用到这三者。Wi-Fi 链路是一个共享的无线电介质;笔记本电脑和服务器各自拥有自己的逻辑地址;消息穿过位于两者之间的种种基础设施,被一跳一跳地转发。用户点击一个链接,笔记本电脑发出一个数据包,剩下的事情由网络处理。
9.1.3. 那摄像头呢?¶
摄像头在网络上扮演的角色与笔记本电脑完全相同。它在加入网络时获得一个逻辑地址,将发出的消息寻址到其他设备的逻辑地址,并让基础设施去路由这些消息。
相较于硬件控制章节,发生变化的是接口。脚本不再是打开一个 UART 实例并向其写入字节,而是打开一个套接字并向其写入字节。套接字是通向网络的一个端点,就像 UART 实例是通向一根线缆的一个端点一样。套接字与线缆之间的各个部分——帧、数据包、路由表、交换机、无线电——全都位于底层,对 Python 代码而言大多是不可见的。
接下来的几页会逐层详细说明这些部分,从而让“打开一个套接字并发送字节”这个抽象显得理所当然,而不是像魔法一样。