由浅入深介绍 Python Websocket 编程

这篇具有很好参考价值的文章主要介绍了由浅入深介绍 Python Websocket 编程。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


1. 为什么使用 Websocket ?

1.1 websocket 协议简介

Websocket协议是对http的改进,可以实现client 与 server之间的双向通信; websocket连接一旦建立就始终保持,直到client或server 中断连接,弥补了http无法保持长连接的不足,方便了客户端应用与服务器之间实时通信。

适用场景
  • html页面实时更新, 客户端的html页面内,用` javascript` 与 server 建立websocket连接,实现页面内容的实时更新。Websocket 非常适合网页游戏、聊天、证券交易等实时应用。
  • 要求保持长连接的实时通信的应用场景。 如基于位置的服务应用,物联网,多方协作软件,在线教育,带社交属性的手机APP等。

实时更新数据场景,为什么不使用AJAX?
AJAX 采用http, 如果要实时更新页面,则需要不断地发送http 请求,无论是否有数据更新,产生大量冗余通信流量。而websocket是长连接双向通信,有数据更新时,服务器向客户机发送通知。

1.2 基本原理

基于TCP,一次握手就能建立连接,支持双向通信,可保持长连接。

python websocket,Python网络通信编程,websocket,python,网络协议,javascript

WebSocket 握手请求消息示例::

GET /chat HTTP/1.1
Host: normal-website.com
Sec-WebSocket-Version: 13
Sec-WebSocket-Key: wDqumtseNBJdhkihL6PW7w==
Connection: keep-alive, Upgrade
Cookie: session=KOsEJNuflw4Rd9BDNrVmvwBF9rEijeE2
Upgrade: websocket

如果 Server 接收连接,返回响应

HTTP/1.1 101 Switching Protocols
Connection: Upgrade
Upgrade: websocket
Sec-WebSocket-Accept: 0FFP+2nmNIf/h+4BP36k9uzrYGk=

响应码为101,表示切换为websocket 协议。

websocket 已得到主流浏览器,各编程语言的广泛支持,基本都提供了WebSocket高阶编程API,在一般场合下,可以替代socket低阶函数编程。python 提供了更简洁的编程实现方式。下面展示了实例代码方式,说明如何开发 Python websocket 服务器代码,python websocket 客户端, 以及javascript websocket 代码。

2. 如何用 Python 搭建 Websocket 服务

python 第3方库 websockets 提供了websocket 实现框架,支持asyncio, 性能强大,稳定性好,可以用于生产环境。

2.1 安装websockets包

pip install websockets

2.2 编写 server 端代码

Websocket服务端代码是面向多用户的长连接,因此本文采用了python3.7 版本的 asyncio 异步方式编写 websocket server 代码。

服务端也可使用 ThreadPoolExecutor 线程池方式同时处理多连接的场景,用户较多时,性能明显不如asyncio异步方式。

websockets 模块 server端的主要方法:

  • recv() 收消息
  • send() 发送消息
  • serve() 创建 server 对象

实现步骤:

  1. 编写websocket 异步任务处理函数handler
  2. 创建1个websocket server 对象
  3. 异步运行 server对象

websocket 地址格式:

  • ws://主机地址:端口号
  • wss://主机地址:端口号, wss表示此连接为https 连接。

下面是具体的代码 server.py

#!/usr/bin/python3
# 主要功能:创建1个基本的websocket server, 符合asyncio 开发要求
import asyncio
import websockets
from datetime import datetime


async def handler(websocket):
    data = await websocket.recv()
    reply = f"Data received as \"{data}\".  time: {datetime.now()}"
    print(reply)
    await websocket.send(reply)
    print("Send reply")


async def main():
    async with websockets.serve(handler, "localhost", 9999):
        await asyncio.Future()  # run forever

if __name__ == "__main__":
    asyncio.run(main())


服务端handler函数代码还有1种写法,适用性更好。

async def handler(websocket):
    async for message in websocket:
	    reply = f"Data received as \"{message}\".  time: {datetime.now()}"
	    print(reply)
        await websocket.send(reply)

Websocket协议本身有心跳机制、连接检测机制,服务端无须关心客户端状态,一旦有异常,会自动断开连接。

Websockets提供了交互式测试命令,现在可以快速测试一下服务端是否能正常工作:
(1) 启动服务器: python server.py
(2) 通过命令行连接服务端,并向发送hello, world 消息,可以看到,收到了服务器的响应。

D:\workplace\python\projects\websock>python -m websockets ws://localhost:9999
Connected to ws://localhost:9999.
> hello, world
< Data received as "hello, world".  time: 2023-04-01 09:24:14.787357
Connection closed: 1000 (OK).

当然实际应用时,应按下面步骤来编写客户端代码。

3. Python websocket 客户端实现代码

websockets 客户端提供的主要方法:

  • connect() 建立与服务器的连接
  • recv(), send() 收发消息
  • close() 显式地关闭连接

下面看一下示例 client.py

import asyncio
import websockets
import time


async def ws_client(url):
    for i in range(1, 40):
        async with websockets.connect(url) as websocket:
            await websocket.send("Hello, I am PyPy.")
            response = await websocket.recv()
        print(response)
        time.sleep(1)

asyncio.run(ws_client('ws://localhost:9999'))


4. Javascript websocket 客户端实现代码

目前主流的浏览器都支持websocket协议。

Javascript websocket 对象的主要属性与方法:
请参考菜鸟教程的这篇文章:https://www.runoob.com/html/html5-websocket.html

示例代码: client.html

<!DOCTYPE HTML>
<html>

<head>
    <meta charset="utf-8">
    <title>websocket demo</title>
  	<meta name="viewport" content="width=device-width, initial-scale=1">
 	 <link rel="stylesheet" href="https://cdn.staticfile.org/twitter-bootstrap/4.3.1/css/bootstrap.min.css">
	<script src="https://cdn.staticfile.org/jquery/3.2.1/jquery.min.js">		</script>
	<script src="https://cdn.staticfile.org/popper.js/1.15.0/umd/popper.min.js"></script>
  	<script src="https://cdn.staticfile.org/twitter-bootstrap/4.3.1/js/bootstrap.min.js"></script>

    <script type="text/javascript">
        function WebSocketTest() {
            text = document.getElementById("div_text");
            if ("WebSocket" in window) {
                // 打开一个 web socket
                var ws = new WebSocket("ws://localhost:9999/handler");

                ws.onopen = function () {
                    // Web Socket 已连接上,使用 send() 方法发送数据
                    ws.send("Javscript发送的数据");
                    text.innerHTML = "数据发送中...";
                    alert("数据发送中...");
                };

                ws.onmessage = function (evt) {
                    var received_msg = evt.data;
                    text.innerHTML = "收到的数据:" + received_msg;
                    alert("数据已接收...");
                };

                ws.onclose = function () {
                    // 关闭 websocket
                    text.innerHTML = "连接已关闭...";
                    alert("连接已关闭...");
                };
            }

            else {
                // 浏览器不支持 WebSocket
                alert("您的浏览器不支持 WebSocket!");
            }
        }
    </script>

</head>

<body>

    <div class="col-md-6 m-5 p-2" id="div_ws">
        <a class="btn btn-primary" href="javascript:WebSocketTest()">连接WebSocket</a>
    </div>
    <div class="col-md-6 border border-primary mx-5 p-2 " id="div_text" style="margin:20px;height:100px;">
        display communicate text
    </div>

</body>

</html>

5. 测试websocket

上述3个文件都放在同1个目录下,打开两个终端窗口,先运行server.py, 再运行 client,py。
Output结果
python websocket,Python网络通信编程,websocket,python,网络协议,javascript
在chrome 或edge 中运行client.html, 可以看到websocket 连接建立,发送,接收,关闭各阶段的状态。
python websocket,Python网络通信编程,websocket,python,网络协议,javascript
能够看到,服务器与客户端之间的通信是双向的,而且是长连接,客户端断开后,服务器仍然保持侦听状态,而且不需要accept操作。websocket发送、接收文件也不需要 socket 对发送窗口 buffer 进行控制,因此是 socket 开发非常好的替代。

注:Python异步websocket服务器最终性能与代码质量、服务器硬件、网络等紧密相关,可以使用 Websocket-benchmarker 测试工具来测试服务器。

6. 服务器向客户端广播消息

websockets 模块支持向所有连接的客户广播消息,
用1个简单的例子来演示,实现步骤:

  • 保存每个 websocket 客户连接
  • 向每个客户发送消息

将前面的server,.py 代码修改后如下:

#!/usr/bin/python3
# 主要功能:创建1个基本的websocket server, 符合asyncio 开发要求
import asyncio
import websockets
from datetime import datetime

# Set of connected clients
connected_clients = set()

async def handler(websocket, path):
    # Add the client to the connected clients set
    connected_clients.add(websocket)    
    try:
        # Keep listening for incoming messages from the client
        async for message in websocket:
            # Broadcast the message to all connected clients
            await broadcast(message)
    finally:
        connected_clients.remove(websocket) 
        
async def broadcast(message):
    # Broadcast the message to all connected clients
    for client in connected_clients:
        await client.send(message)

async def main():
    async with websockets.serve(handler, "localhost", 9998):
        await asyncio.Future()  # run forever
        loop = asyncio.get_running_loop() #获取当前event_loop对象
        loop.create_task(broadcast())     # 添加新的异步广播任务

if __name__ == "__main__":
    asyncio.run(main())

本例中,当服务器收到1条消息时,会广播给所有用户。文章来源地址https://www.toymoban.com/news/detail-780629.html

到了这里,关于由浅入深介绍 Python Websocket 编程的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 大学生精通Python从由浅入深(Python基础篇)

    看到这位 头发浓密 大叔了吗!1989年,为了打发圣诞节假期,龟叔(吉多·范·罗苏姆)开始写Python语言的编译器 。 1991年 ,第一个Python编译器诞生 Python这个名字,来自龟叔所挚爱的电视剧Monty Python’s Flying Circus (蒙蒂·蟒蛇的飞行马戏团) 我们为什么要学习这一项语言,Pytho

    2024年02月10日
    浏览(33)
  • 由浅入深掌握各种 Python 进程间通信方式(建议收藏)

    转载本文请注明 CSDN 链接处: https://blog.csdn.net/captain5339/article/details/129099833 Python代码效率由于受制于GIL全局锁限制,多线程不能利用多核CPU来加速,而 多进程 方式却可以绕过GIL限制, 发挥多CPU加速的优势,达到提高程序的性能的目的。 然而进程间通信却是不得不考虑的问题。

    2024年02月02日
    浏览(39)
  • Python+大数据-大学生精通Python从由浅入深(Python基础篇)

    看到这位 头发浓密 大叔了吗!1989年,为了打发圣诞节假期,龟叔(吉多·范·罗苏姆)开始写Python语言的编译器 。 1991年 ,第一个Python编译器诞生 Python这个名字,来自龟叔所挚爱的电视剧Monty Python’s Flying Circus (蒙蒂·蟒蛇的飞行马戏团) 我们为什么要学习这一项语言,Pytho

    2024年02月13日
    浏览(35)
  • Docker由浅入深(一)

    容器化技术介绍 介绍容器化之前,我们得先知道,为什么会出现容器化,容器化之前都经历了什么 物理机时代 部署非常慢 成功很高 浪费资源 难于扩展与迁移 受制于硬件 虚拟化时代 在同一个物理机上安装多个虚拟机,每个虚拟机安装操作系统和应用, 虚拟机之间物理资源

    2024年02月03日
    浏览(35)
  • 由浅入深了解HashMap源码

           由经典面试题引入,讲解一下HashMap的底层数据结构?这个面试题你当然可以只答,HashMap底层的数据结构是由(数组+链表+红黑树)实现的,但是显然面试官不太满意这个答案,毕竟这里有一个坑需要你去填,那就是在回答HashMap的底层数据结构时需要考虑JDK的版本,因

    2023年04月13日
    浏览(30)
  • 【个人笔记】由浅入深分析 ClickHouse

    项目中不少地方使用到ClickHouse,就对它做了一个相对深入一点的了解和研究。并对各种知识点及整理过程中的一些理解心得进行了汇总并分享出来,希望对其他同学能有帮助。 本文主要讲解ClickHouse的特点、读写过程、存储形式、索引、引擎、物化视图等特性。 适合 入门和

    2024年01月20日
    浏览(34)
  • React - redux 使用(由浅入深)

    中文文档: http://www.redux.org.cn/ 英文文档: https://redux.js.org/ Github: https://github.com/reactjs/redux 可直接参照 目录十 进行使用 react-redux redux 是一个专门用于做状态管理的JS库(不是react插件库)。 它可以用在 react, angular, vue 等项目中, 但基本与 react 配合使用。 作用: 集中式管理 re

    2024年02月07日
    浏览(38)
  • 由浅入深Netty代码调优

    序列化,反序列化主要用在消息正文的转换上 序列化时,需要将 Java 对象变为要传输的数据(可以是 byte[],或 json 等,最终都需要变成 byte[]) 反序列化时,需要将传入的正文数据还原成 Java 对象,便于处理 目前的代码仅支持 Java 自带的序列化,反序列化机制,核心代码如

    2024年02月05日
    浏览(31)
  • 手拉手Vue组件由浅入深

    组件 (Component) 是 Vue.js 最强大的功能之一,它是html、css、js等的一个聚合体,封装性和隔离性非常强。 组件化开发:     1、将一个具备完整功能的项目的一部分分割多处使用     2、加快项目的进度     3、可以进行项目的复用 组件注册分为:全局注册和局部注册 目录

    2024年01月18日
    浏览(34)
  • 由浅入深理解C#中的事件

    本文较长,给大家提供了目录,可以直接看自己感兴趣的部分。 前面介绍了C#中的委托,事件的很多部分都与委托类似。实际上,事件就像是专门用于某种特殊用途的简单委托,事件包含了一个私有的委托,如下图所示: 有关事件的私有委托需要了解的重要事项如下: 1、事

    2024年02月03日
    浏览(32)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包