iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > Python >python websockets实现server和client的通信
  • 474
分享到

python websockets实现server和client的通信

pythonwebsocket服务器Poweredby金山文档 2023-09-02 19:09:44 474人浏览 八月长安

Python 官方文档:入门教程 => 点击学习

摘要

项目地址:https://github.com/aaugustin/websockets 文档地址:https://websockets.readthedocs.io/en/stable/ 1、websockets WEBSocket

项目地址:https://github.com/aaugustin/websockets

文档地址:https://websockets.readthedocs.io/en/stable/

1、websockets

WEBSocket是一种在单个tcp连接上进行全双工通讯的协议,使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在WebSocket api中,浏览器和服务器只需要完成一次握手,两者之间就可以创建持久性的连接,并进行双向数据传输。主要有如下特点:

1)建立在 TCP 协议之上,服务器端的实现比较容易;

2)与 Http 协议有着良好的兼容性。默认端口也是80和443,并且握手阶段采用 HTTP 协议,因此握手时不容易屏蔽,能通过各种 HTTP 代理服务器;

3)数据格式比较轻量,性能开销小,通信高效;

4)可以发送文本,也可以发送二进制数据;

5)没有同源限制,客户端可以与任意服务器通信;

6)协议标识符是ws(如果加密,则为wss),服务器网址就是 URL。

包安装:pip install websockets

2、websockets常用函数

serve:在server端使用,等待客户端的连接。如果连接成功,返回一个websocket。

connect:在client端使用,用于建立连接。

send:发送数据,server和client双方都可以使用。

recv:接收数据,server和client双方都可以使用。

close:关闭连接,server和client双方都可以使用。

3、一个简单的服务端客户端测试程序

Server端代码:

websockets.serve(),用于等待客户端的连接。如果客户端调用connect方法成功,则返回一个websocket。

import asyncioimport websocketsIP_ADDR = "127.0.0.1"IP_PORT = "8888"async def server_hands(websocket):    """ 握手,通过接收hello,发送"123"来进行双方的握手    """    while True:        recv_text = await websocket.recv()        print("recv_text=" + recv_text)        if recv_text == "hello":            print("connected success")            await websocket.send("123")            return True        else:            await websocket.send("connected fail")async def server_recv(websocket):    """ 接收从客户端发来的消息并处理,再返给客户端ok。    """    while True:        try:            recv_text = await websocket.recv()            print("recv:", recv_text)            await websocket.send("ok!!!")        except websockets.ConnectionClosed as e:            # 客户端关闭连接,跳出对客户端的读取,结束函数            print(e.code)            await asyncio.sleep(0.01)            breakasync def server_run(websocket, path):    """ 握手并且接收数据    :param websocket:    :param path:    """    # 下面两个函数顺序执行    await server_hands(websocket)  # 握手    await server_recv(websocket)  # 接收客户端消息并处理# main functionif __name__ == '__main__':    print("======server main begin======")    server = websockets.serve(server_run, IP_ADDR, IP_PORT)  # 服务器端起server    asyncio.get_event_loop().run_until_complete(server)  # 事件循环中调用    asyncio.get_event_loop().run_forever()  # 一直运行

Client端代码:

通过调用connect方法与服务的建立通信。

通过发送"hello",接收"123"来进行双方握手的校验,只有握手成功,才可以继续发送和接收数据。

import asyncioimport websocketsIP_ADDR = "127.0.0.1"IP_PORT = "8888"async def client_hands(websocket):    """ 握手,通过发送hello,接收"123"来进行双方的握手。        若成功,则跳出循环,结束函数;若失败,则继续发送hello.    """    while True:        await websocket.send("hello")        response_str = await websocket.recv()        if "123" in response_str:            print("握手成功")            return Trueasync def client_send(websocket):    """ 向服务器端发送消息    """    while True:        input_text = input("input text: ")        if input_text == "exit":            print(f'"exit", bye!')            await websocket.close(reason="exit")  # 关闭本次连接            return False        # 发送数据并打印服务端返回结果        await websocket.send(input_text)        recv_text = await websocket.recv()        print(f"{recv_text}")async def client_run():    """ 进行websocket连接    """    server_url = "ws://" + IP_ADDR + ":" + IP_PORT    print("websockets server url: ", server_url)    try:        async with websockets.connect(server_url) as websocket:            # 下面两行同步进行            await client_hands(websocket)  # 握手            await client_send(websocket)  # 发数据    except ConnectionRefusedError as e:        # 服务端未启动,或连接失败时退出.        print("e:", e)        return# main functionif __name__ == '__main__':    print("======client main begin======")    asyncio.get_event_loop().run_until_complete(client_run())  # 等价于asyncio.run(client_run())

运行结果:

服务端启动后,客户端依次输入111、exit。

服务端:

python server_1.py======server main begin======recv_text=helloconnected successrecv: 1111000

客户端:

>Python client_1.py======client main begin======websockets server url:  ws://127.0.0.1:8888握手成功input text: 111ok!!!input text: exit"exit", bye!

4、重连机制

上面的例子中连接一段时间后,自动断开。再次发送请求时就会失败!所以,对客户端代码进行改进。我们先要知道的是:

1)当服务端拒绝连接(没有打开 ws ),客户端会抛出 ConnectionRefusedError 错误。

2)当服务端将连接上的 ws 关闭时(无论是正常关闭还是异常关闭),会抛出 ConnectionClosed 错误(是 websockets 内的错误类)。

4.1、捕获异常后重连

引用https://sakina.blog.csdn.net/article/details/108090049中的例子,捕获上述两个异常后重连。

import asyncioimport websockets as wsfrom websockets import ConnectionClosedcount = 0async def hello():    uri = "ws://localhost:8765"    while True:        try:            async with ws.connect(uri) as websocket:                await websocket.send('start')                while True:                    try:                        await websocket.recv()                    except ConnectionClosed as e:                        print(e.code)                        if e.code == 1006:print('restart')await asyncio.sleep(2)break        except ConnectionRefusedError as e:            print(e)            global count            if count == 10:                 return            count += 1            await asyncio.sleep(2)asyncio.get_event_loop().run_until_complete(hello())

这段代码的核心是两个 while :

第一层 while 的作用是循环 ws 连接上下文,当服务端拒绝连接时,会抛出 ConnectionRefusedError ,我们每隔 2 秒重试一次,最多重试 10 次。

第二层 while 的作用是保证 ws 连接一直处于接收状态(长连接),当 ws 被服务端关闭时,会抛出 ConnectionClosed ,一般我们会收到 1000 正常关闭码和 1006 服务端内部错误异常关闭码两种,在上文的代码中,我们收到异常 1006 关闭码时,就 break 退出 while 循环,从而自动关闭 ws 连接上下文,进行一次新的 ws 上下文连接。

注:在第二层不可以使用 continue 跳过本次循环,必须要重建 ws 上下文连接,否则 ws 连接总是处于被关闭状态。

4.2、定时任务

如果要加入定时任务,如自定义的心跳,我们需要创建一个异步 task 任务。任务函数如下:

async def ping(ws):    while True:        try:            await ws.send('ping')            await asyncio.sleep(10)        except:            break

之后在 ws 上下文流程中加入异步 task 执行任务。

async with ws.connect(uri) as websocket:    await websocket.send('start')    asyncio.create_task(ping(websocket))    while True:        try:            await websocket.recv()        except ConnectionClosed as e:            print(e.code)            if e.code == 1006:                print('restart')                await asyncio.sleep(2)                break

函数 ping() 是我们自定义的心跳 ping ,他会每隔 10 秒给服务端发送文本为 ping 的消息。

无论服务端将 ws 关闭还是 ws 连接不成功,此 task 必由于 ws 不可用而报错,我们 break 掉该 while 循环即可,从而此 task 执行完毕,当 ws 又被成功建立时,新的 task 定时任务又会被启动。

4.3、测试代码重连实现

支持:服务端未启动时重连;客户端主动退出;服务端异常时重连。

import asyncioimport websocketsfrom enum import Enum, unique@uniqueclass WSStatus(Enum):    Exit = 1  # 用户退出    Interrupt = 2  # 连接中断    Error = 3  # 程序内部错误    Success = 4  # 调用成功    Fail = 5  # 调用失败IP_ADDR = "127.0.0.1"IP_PORT = "8888"async def client_hands(websocket):    """ 握手,通过发送hello,接收"123"来进行双方的握手。        若成功,则跳出循环,结束函数;若失败,则继续发送hello.    """    while True:        await websocket.send("hello")        response_str = await websocket.recv()        if "123" in response_str:            print("握手成功")            return WSStatus.Successasync def client_send(websocket):    """ 向服务器端发送消息    """    input_text = input("input text: ")    if input_text == "exit":        print(f'"exit", bye!')        await websocket.close(reason="exit")  # 关闭本次连接        return WSStatus.Exit    # 发送数据并打印服务端返回结果    r = await websocket.send(input_text)    print("r:", r)    recv_text = await websocket.recv()    print(f"{recv_text}")    return WSStatus.Successasync def client_run():    """ 进行websocket连接    """    con_count = 0    MAX_RECONNECT_COUNT = 10  # 定义最大重连次数    server_url = "ws://" + IP_ADDR + ":" + IP_PORT    print("websockets server url: ", server_url)    while True:        try:            async with websockets.connect(server_url) as websocket:                # 下面两行同步进行                await client_hands(websocket)  # 握手                r = None                while True:                    try:                        r = await client_send(websocket)  # 发数据                        # print("r:", r)                        if r == WSStatus.Exit:  # 程序内部正常退出break                    except websockets.ConnectionClosed as e:                        print(e.code)                        if e.code == 1006:print('restart')await asyncio.sleep(0.1)break                if r == WSStatus.Exit:  # 程序内部正常退出                    break        except ConnectionRefusedError as e:            # 服务端未启动,或连接失败时退出.            print("e:", e)            if con_count == MAX_RECONNECT_COUNT:                return            con_count += 1            print(f"reconnect {con_count} times...")            await asyncio.sleep(0.01)# main functionif __name__ == '__main__':    print("======client main begin======")    asyncio.get_event_loop().run_until_complete(client_run())  # 等价于asyncio.run(client_run())

5、加密,增加headers调用

headers = {    'User-Agent': 'Mozilla/5.0 (windows NT 10.0; Win64; x64) AppleWebKit/537.36 (Khtml, like Gecko) Chrome/102.0.0.0 Safari/537.36',    'Origin': 'https://live.bilibili.com',    'Connection': 'Upgrade',    'Accept-Language': 'zh-CN,zh;q=0.9',}...sync with websockets.connect(self.wss_url,                 extra_headers=headers                ) as websocket:

参考:

1、python websockets的使用,实现server和client的通信

https://blog.csdn.net/liranke/article/details/120533682

2、wss连接的一些坑

https://blog.csdn.net/zouzhe121/article/details/103122532

3、测试用例代码

https://blog.csdn.net/liranke/article/details/120533682

4、python websockets 全双工通信

https://blog.csdn.net/qq_42195302/article/details/120150438

5、Python异步高性能websockets库简单入门(含重连机制与定时任务)

https://sakina.blog.csdn.net/article/details/108090049

6、python | websockets库的使用(增加headers调用)

https://www.cnblogs.com/Mz1-rc/p/16472294.html

来源地址:https://blog.csdn.net/weixin_34910922/article/details/128794946

--结束END--

本文标题: python websockets实现server和client的通信

本文链接: https://www.lsjlt.com/news/391289.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • python websockets实现server和client的通信
    项目地址:https://github.com/aaugustin/websockets 文档地址:https://websockets.readthedocs.io/en/stable/ 1、websockets WebSocket...
    99+
    2023-09-02
    python websocket 服务器 Powered by 金山文档
  • Golang简单实现http的server端和client端
    介绍 HTTPS (Secure Hypertext Transfer Protocol)安全超文本传输协议,是一个安全通信通道,它基于HTTP开发用于在客户计算机和服务器之间交换...
    99+
    2024-04-02
  • html5中怎么利用websockets实现全双工通信
    本篇文章为大家展示了html5中怎么利用websockets实现全双工通信,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。1、WebSocket握手为了建立WebSo...
    99+
    2024-04-02
  • python和JavaScript通信怎么实现
    本文小编为大家详细介绍“python和JavaScript通信怎么实现”,内容详细,步骤清晰,细节处理妥当,希望这篇“python和JavaScript通信怎么实现”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。j...
    99+
    2023-06-30
  • 如何在Bokeh中使用回调和WebSockets实现服务器和客户端之间的实时通信
    非常抱歉,由于您没有提供文章标题,我无法为您生成一篇高质量的文章。请您提供文章标题,我将尽快为您生成一篇优质的文章。...
    99+
    2024-05-21
  • Python实现进程同步和通信
    引例: 如之前创建多进程的例子 # -*- coding:utf-8 -*- from multiprocessing import Process,Pool import os,time def run_proc(name):...
    99+
    2023-01-31
    进程 通信 Python
  • python 实现 RPC 通信
     例子: Python RPC Server import SimpleXMLRPCServer class MyObject:      def sayHello(self):          return "hello ZQF,...
    99+
    2023-01-31
    通信 python RPC
  • Vue和Flask通信的实现
    安装axios和实现通信 这里我们通过axios来连接Vue前端和Flask后端,使用AJAX请求进行通信。使用如下命令安装 npm install axios axios的使...
    99+
    2024-04-02
  • python 实现Modebus 通信(pyModbusTCP )
            尽管python 并不适合实时控制,但是它编写程序实在是太方便了。至少在程序快速成型和验证过程中可以使用Python 来实现,另一方面,Python 强大的数值计算和图形显示能力也能够实现modbus 设备的远程监控,数据采...
    99+
    2023-08-30
    python Modbus
  • Node.js多页面如何实现数学运算的client端和server端
    这篇文章将为大家详细讲解有关Node.js多页面如何实现数学运算的client端和server端,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。具体如下:1、server端...
    99+
    2024-04-02
  • 【Python】Python实现串口通信(Python+Stm32)
    🎉欢迎来到Python专栏~Python实现串口通信 ...
    99+
    2023-08-31
    python stm32 开发语言 串口通信 嵌入式硬件 Python+Stm32
  • 微信小程序的Socket.io client如何实现
    这篇“微信小程序的Socket.io client如何实现”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“微信小程序的Sock...
    99+
    2023-06-26
  • JavaScript和Go:如何实现实时通信?
    实时通信已经成为了现代Web应用程序的关键特性之一。它使得用户能够在不刷新页面的情况下实时接收来自服务器的更新,从而提高了用户体验。这种通信可以使用多种技术来实现,其中JavaScript和Go是两种最常用的技术之一。 在这篇文章中,我们...
    99+
    2023-08-17
    http javascript 实时
  • Node与Python双向通信的实现方法
    这篇文章主要介绍“Node与Python双向通信的实现方法”,在日常操作中,相信很多人在Node与Python双向通信的实现方法问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Node与Python双向通信的实...
    99+
    2023-06-20
  • HTTPS通信的C++实现
     HTTPS是以安全为目标的HTTP通道,简单讲是HTTP的安全版。即HTTP下加入SSL层,HTTPS的安全基础是SSL,因此加密的详细内容就需要SSL。Nebula是一个为开发者提供一个快速开发高并发网络服务程序或搭建高并发分布式服务集...
    99+
    2023-06-06
  • C#如何实现TCP和UDP通信
    本篇内容主要讲解“C#如何实现TCP和UDP通信”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“C#如何实现TCP和UDP通信”吧!C#在命名空间System.Net.Sockets中对伯克利套接...
    99+
    2023-07-05
  • python如何实现socket简单通信
    这篇文章将为大家详细讲解有关python如何实现socket简单通信,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。首先先来简单介绍下socket:(具体更详细介绍的可以在网上找找,都讲得非常详细),这里主...
    99+
    2023-06-14
  • python套接字socket通信在实现
    本文小编为大家详细介绍“python套接字socket通信在实现”,内容详细,步骤清晰,细节处理妥当,希望这篇“python套接字socket通信在实现”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。一、初步认识s...
    99+
    2023-06-29
  • Python怎么实现UDP与TCP通信
    这篇文章主要介绍了Python怎么实现UDP与TCP通信的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Python怎么实现UDP与TCP通信文章都会有所收获,下面我们一起来看看吧。1. UDPUDP是一种无连接...
    99+
    2023-07-05
  • 使用python实现UDP通信方式
    目录python UDP通信对UDP协议的理解Socket简介UDP特点UDP中客户端和服务器端交互 UDP网络通信过程 多线程聊天室服务器端的实现UDP中广播p...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作