Python中WebSocket服务器的基本概念

什么是WebSocket服务器?

简而言之,WebSocket服务器是在遵循协议调用WS(或WSS)的任何TCP端口服务器上侦听的应用程序。

通常,反向代理(例如HTTP服务器)用于检测Websocket握手,对其进行处理并将这些客户端发送到WebSocket服务器。WebSocket协议旨在与现有的Web基础结构良好配合。作为此设计原则的一部分,WebSocket连接从HTTP连接开始,并与WebSocket之前的版本完全向后兼容。从HTTP到WebSocket的协议转换称为握手。

客户端发送升级头:

    --- request header ---
    GET / HTTP/1.1
    Upgrade: websocket
    Connection: Upgrade
    Host: localhost:4040
    Origin: http://localhost:4040
    Sec-WebSocket-Key: q0+vBfXgMvGGywjDaHZWiw==
    Sec-WebSocket-Version: 13

如果服务器理解WebSocket协议,则表示它同意通过升级标头进行协议切换。

    -----------------------
    --- response header ---
    HTTP/1.1 101 Switching Protocols
    Upgrade: websocket
    Connection: Upgrade
    Sec-WebSocket-Accept: /YqMq5iNGOMjtELPGCZsnozMSlw=
    Date: Sun, 15 Sep 2019 23:34:04 GMT
    Server: Python/3.7 websockets/8.0.2
    -----------------------

此时,HTTP连接断开,并由基础TCP / IP连接上的WebSocket连接代替。WebSocket与HTTP类似,默认情况下使用HTTP(80)和HTTPS(443)。

何时何地使用WebSockets?

  1. 实时应用程序–需要在没有客户端请求数据的情况下更新UI的情况。在这里,WebSockets比使用传统的AJAX轮询更快,后者使用HTTP

  2. 游戏应用

  3. 聊天应用

什么时候不使用WebSockets?

不需要实时更新。WebSockets,因为在组件之一关闭连接之前,该连接一直处于活动状态。相反,RESTful服务足以从服务器获取数据。

使用python库实现WebSocket服务器

Python提供了许多库来实现WebSocket服务器。以下是市场上可用的少数几个。这些库可以通过Pypi轻松安装在虚拟环境Anaconda环境中

  • WebSockets:https://pypi.org/project/websockets/

  • 龙卷风:https://pypi.org/project/tornado/

用于实现WebSocket服务器的示例代码

1)使用WebSockets库(ws_server.py)

import asyncio
import websockets
import time
import json

async def say_hello(websocket, path):
    while True:
        await websocket.send("hello world")
        time.sleep(10)

# 服务器在localhost和端口4040中启动
start_server = websockets.serve(say_hello,'localhost',4040)
asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()

2)使用龙卷风库(tornado_ws_server.py)

'''
    This module hosts a websocket server using tornado
    libraries
'''
import tornado.web
import tornado.httpserver
import tornado.ioloop
import tornado.websocket as ws
from tornado.options import define, options
import time

define('port', default=4041, help='port to listen on')


class web_socket_handler(ws.WebSocketHandler):
    '''
    This class handles the websocket channel
    '''
    @classmethod
    def route_urls(cls):
        return [(r'/',cls, {}),]
    
    def simple_init(self):
        self.last = time.time()
        self.stop = False

    
    def open(self):
        '''
            client opens a connection
        '''
        self.simple_init()
        print("New client connected")
        self.write_message("You are connected")

        
    def on_message(self, message):
        '''
            Message received on the handler
        '''
        print("received message {}".format(message))
        self.write_message("You said {}".format(message))
        self.last = time.time()
    
    def on_close(self):
        '''
            Channel is closed
        '''
        print("connection is closed")

    
    def check_origin(self, origin):
        return True


def initiate_server():
    #创建一个龙卷风应用程序并提供网址
    app = tornado.web.Application(web_socket_handler.route_urls())
    
    #设置服务器
    server = tornado.httpserver.HTTPServer(app)
    server.listen(options.port)
    
    #开始io /事件循环
    tornado.ioloop.IOLoop.instance().start()


if __name__ == '__main__':
    initiate_server()

设置环境以实现WebSocket服务器

  • 创建虚拟环境
    -bash-4.2 $python3 -m venv venv

  • 源(或激活)虚拟环境
    -bash-4.2 $源venv / bin / activate

  • 使用pip安装所需的库

  • 	(venv) -bash-4.2$ pip3 install websockets
    Collecting websockets
      Downloading https://files.pythonhosted.org/packages/f0/4b/ad228451b1c071c5c52616b7d4298ebcfcac5ae8515ede959db19e4cd56d/websockets-8.0.2-cp36-cp36m-manylinux1_x86_64.whl (72kB)
        100% |████████████████████████████████| 81kB 2.1MB/s
    Installing collected packages: websockets
    Successfully installed websockets-8.0.2
     (venv) -bash-4.2$
    	
    (venv) -bash-4.2$ pip3 install tornado
    Collecting tornado
      Using cached https://files.pythonhosted.org/packages/30/78/2d2823598496127b21423baffaa186b668f73cd91887fcef78b6eade136b/tornado-6.0.3.tar.gz
    Installing collected packages: tornado
      Running setup.py install for tornado ... done
    Successfully installed tornado-6.0.3
     (venv) -bash-4.2$
    
    Execute the sample websocket server
    	Python3 tornado_ws_server.py
    		Or 
    	Python3 ws_server.py

客户端服务器交互的Wireshark跟踪

Python中的Web套接字

参考文献:

  • https://github.com/postrank-labs/goliath/issues/199

  • https://github.com/tinyproxy/tinyproxy/issues/101