大家好,又见面了,我是你们的朋友全栈君。
作者:小小明
在前面的用Tornado实现web聊天室一文中介绍了python实现websocket的方法,这篇文章将要分享如何用python作为客户端获取websocket接口的数据。
前文链接:https://blog.csdn.net/as604049322/article/details/112386560
websocket的使用
WebSocket 是一种在单个 TCP/TSL 连接上,进行全双工、双向通信的协议。WebSocket 可以让客户端与服务器之间的数据交换变得更加简单高效,服务端也可以主动向客户端推送数据。在 WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就可以直接创建持久性的连接,并进行双向数据传输。
WebSocket 可以在连续发送数据的同时不断地接受消息。并不会像 REST 一样,每发送一个请求,要等待服务器完成请求、完全回复之后,再进行下一个请求。”全双工“可以理解为在请求的同时也可以接受消息。
websocket与传统http协议的对比:
文章目录
- websocket的使用
-
- websocket服务端
- JavaScript的websocket客户端
- Python的websocket同步客户端
- Python的websockets异步客户端
websocket服务端
首先启动一个简单的websocket服务端用于测试,代码如下:
代码语言:javascript复制__author__ = 'xiaoxiaoming'
import datetime
from abc import ABC
import tornado.httpserver
import tornado.ioloop
import tornado.web
from tornado.options import define, options
from tornado.websocket import WebSocketHandler
define("host", default="127.0.0.1", type=str)
define("port", default=8000, type=int)
class ChatHandler(WebSocketHandler, ABC):
users = set() # 用来存放在线用户的容器
def open(self):
self.users.add(self) # 建立连接后添加用户到容器中
for u in self.users: # 向已在线用户发送消息
u.write_message(
f"[{self.request.remote_ip}]-[{datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}]-进入聊天室")
def on_message(self, message):
for u in self.users: # 向在线用户广播消息
u.write_message(u"[%s]-[%s]-说:%s" % (
self.request.remote_ip, datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"), message))
def on_close(self):
self.users.remove(self) # 用户关闭连接后从容器中移除用户
for u in self.users:
u.write_message(
f"[{self.request.remote_ip}]-[{datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}]-离开聊天室")
def check_origin(self, origin):
return True # 允许WebSocket的跨域请求
if __name__ == '__main__':
app = tornado.web.Application([
(r"/", ChatHandler),
])
http_server = tornado.httpserver.HTTPServer(app)
http_server.listen(options.port)
print(f"http://{options.host}:{options.port}")
tornado.ioloop.IOLoop.current().start()
以上代码依赖于tornado,没有安装的需要使用pip安装:
代码语言:javascript复制pip install tornado
JavaScript的websocket客户端
websocket的客户端使用JavaScript会非常简单,只需要在游览器后台执行:
代码语言:javascript复制var ws = new WebSocket("ws://127.0.0.1:8000/"); // 新建一个ws连接
ws.onmessage = function (evt) {
// 收到服务器发送的消息后执行的回调
console.log(evt.data); // 接收的消息内容在事件参数evt的data属性中
};
即可在游览器连接上websocket服务端,并在获得消息时自动控制台显示。
执行以下命令可向服务端发送消息:
代码语言:javascript复制ws.send("xxxx")
在运行上面的服务端后,我们在游览器中执行以上的JavaScript代码:
服务端只是简单把从客户端收到的所有的消息,加上ip和时间发送给所有的客户端。从上面的结果可以看到我们的测试服务端顺利运行。
Python的websocket同步客户端
那么python中如何实现这样的客户端呢?代码如下:
代码语言:javascript复制#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# 创建时间:2021/1/24 17:06
__author__ = 'xiaoxiaoming'
import time
import websocket
import _thread
# 在接收到服务器发送消息时调用
def on_message(ws, message):
print('Received: ' message)
# 在和服务器建立完成连接时调用
def on_open(ws):
# 线程运行函数
def process():
while True:
s = input("要发送的内容(quit表示退出):")
if s == "quit":
break
ws.send(s)
# 休息 0.2 秒先接收服务器回复的消息
time.sleep(0.2)
# 关闭 Websocket 的连接
ws.close()
print("Websocket closed")
# 在另一个线程运行 gao() 函数
_thread.start_new_thread(process, ())
if __name__ == "__main__":
ws = websocket.WebSocketApp("ws://127.0.0.1:8000/",
on_message=on_message,
on_open=on_open)
ws.run_forever()
上面的代码on_open方法启动了一个用于向服务端发送消息的线程。
运行后,也可以顺利看到执行效果:
如果上面已经连接的预览器没有关闭的话也可以收到消息:
需要注意的是这个客户端依赖的包是websocket_client
,而不是websocket
,如果你缺少这个库,需要执行:
pip -m install websocket_client
来安装。
Python的websockets异步客户端
python支持websocket客户端除了上面这种同步接口,还提供了websockets这种协程实现的异步接口,在我们不需要使用input这种阻塞式方法时,建议直接使用websockets。
需要以下命令来安装:
代码语言:javascript复制pip install websockets
测试代码:
代码语言:javascript复制__author__ = 'xiaoxiaoming'
import asyncio
import websockets
async def process():
async with websockets.connect("ws://127.0.0.1:8000/") as ws:
while True:
try:
message = await asyncio.wait_for(ws.recv(), timeout=30)
print('Received: ' message)
except asyncio.TimeoutError as e:
continue
except websockets.exceptions.ConnectionClosed as e:
print('连接已经关闭')
break
asyncio.run(process())
如果是python3.7以下的版本:
代码语言:javascript复制asyncio.run(process())
需要更换为:
代码语言:javascript复制loop = asyncio.get_event_loop()
loop.run_until_complete(process())
loop.close()
当然建议直接使用python3.7以上版本的协程。
运行后可以顺利的收到从服务端发来的消息:
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/159893.html原文链接:https://javaforall.cn