一个最小的PythonWebsocket服务器

即时交互的Web APP的未来已经到来.事实上,自从2009年12月Google发布Chrome的4.0.249.0版本,WebSocket就已经随处可见了.在普通网页上和服务器建立一个链接并通信就是这样简单:

这段代码建立了一个网页到服务器的双向链接,网页和服务器可以相互发消息,每次发消息前不需要再次建立链接.如果用ajax来实现,我们需要使用很多奇技淫巧,来让链接在消息发送完成后不被关掉.

Websocket的出现大大加速了网页和服务器之间交换消息的速度.这里我录制了一个视频,视频中有两个音频播放器,这两个播放器都是在网页上,通过WebSocket连接到连接到音频服务器,从而间接地连接到spotify的音乐流服务.看,它们几乎是同步的!要注意,当我拖动进度条的时候,这个变化要发送一个消息给服务器,服务器还要发送一个消息给另一个客户端,另一个客户端才能够作出反应.但是我们看到,视频中两个客户端之间几乎没有任何延迟.

已经有很多项目试着去提供WebSocket的服务端解决方案了.其中一些项目主要目的是演示这个概念,而另外一些则是切实可用的解决方案.本篇博文的目的是用尽量少的代码,让消息能够通过Websocket从一个浏览器传送到服务器端,并由服务器发送给另外一个浏览器.

为了完成这个工作我们需要一些背景知识.首先是WebSocket API的草案(#network),这个草案指明了在网页中你应该如何通过js链接服务器的socket,而Chrome底层也遵照这个草案实现了接口.

其次是Websocket协议,这个协议说明了在服务器端我们应该如何包装和解析消息,协议中说明客户端请求的头部,应该发送类似于下面这样的文本到服务器,这里也就是Chrome应该这样做,自然地,我们的服务器就会接收到这样的内容

服务器接受这个消息,验证这个消息,并以下面这个格式应答

如果这个握手的消息客户端验证失败,客户端就会关闭这个链接.所以服务器返回的内容中WebSocket-Origin和WebSocket-Location一定要和发来的消息保持一致.否则Chrome会认为这个消息有问题,然后丢弃它.

到这里,Python服务器的代码类似于这样:

你可能会注意到,我这里使用了Python的标准库socket.客户端发来的消息会被去掉两端的00和ff,发回去的消息又会带上相同的两端标识.一个128比特的数据包中可能包含有多个消息的信息,它们会被正确地解析,必要的时候,一些比特会被保留并和下一个数据包中的数据合并在一起.

这篇博客的示例实际上用处不大,但是它演示了WebSocket的潜力.希望这篇博客能让大家对这个交互流程有更深刻的认识.

英文原文:

译者:诗书塞外