WebSocketを今一度整理その1
2025-03-24 2025-03-25

WebSocketって、枯れた技術に分類されると思うけど。
WebSocketってやつですが。
もう10年以上たってるし、そろそろ枯れた技術ではあるけれど、
aJaxのように、使われつづける技術だと思うし、
とりあえず、Pythonで使うことを念頭にまとめてみます。
例によって、、『使われ方』から考えてみますよ。
#定義
# hiraWSSV がWeboSkcetServerの基本のクラス
class CustomXXX_WS_SV(hiraWSSV):
async def async_connect(self,websocket):
あれこれ
async def async_message(self,ws,mes):
あれこれ
async def async_except(self,e,idx):
あれこれ
async def async_except_after(self): # WebSocketを切り離した後に何かを実行するため用
あれこれ
#使う
host=xxxxxx
port=zzzzzz
A = CustomXXX_WS_SV()
A.setParent(self)
A.RunForever(host,port) #※
#または、(上記※)
S = hiraThread(target = A.RunForever,args=(host,port,))
S.start()
基本的なライブラリは
そうなんですよね。これが、WebSocket関係って、Server,Clientとか、実にいろんなライブラリがあって、あれこれいろいろpipして使ってきたわけですが、、もうなんかシンプルに最低限の機能があれば、自分で気の利いたやつを作ればよいので、ここではこの一択です。
pip install websockets
非同期というやつ
まぁWebSocketの限らず、通信系はとくに、非同期が重要になるわけで、、
もちろん、マルチスレッドも使うわけですが、、websocketsライブラリは、
async await 前提のようなつくりになってるので、そこをうまく理解して自分のライブラリを書かないと、、です。
まぁそれには、、PythonのEvent-Loopに関して、一応把握しておけば良いかなと。
ということで、作ってみました
#-----------------------------------------------------------------------------------
import const
import hiraide
import hiraSetting
import tracemalloc
import time
import asyncio
import websockets
import uuid
from hiraThread import hiraThread
class hiraWSSV:
parent = None
cWS = None
AR = []
def __init__(self):
self.cWS = None
self.AR = []
self.myLoop = asyncio.new_event_loop()
asyncio.set_event_loop(self.myLoop)
def setParent(self,parent):
self.parent = parent
def searchWs(self,ws):
n = len(self.AR)
for w in range(n):
if self.AR[w]["ws"] == ws:
return w
return -1
async def async_connect(self,websocket):
print(f"async_connect:websocket:{websocket}")
pass
async def async_message(self,ws,mes):
print(f"async_message:mes:{mes}")
await self.async_send(ws,"FROM async_message")
pass
async def async_except(self,e,idx):
print(f"async_except:idx:e:[{idx}]:{e}")
pass
async def async_send(self,ws,mes):
await ws.send(mes)
pass
async def async_close(self,idx):
try:
ws = self.AR[idx]["ws"]
await ws.close()
self.AR.pop(idx)
except Exception as e:
pass
def sendA(self,ws,mes):
self.myLoop.run_until_complete(self.async_send(ws,mes))
def send(self,idx,mes):
if(idx >= 0):
self.myLoop.run_until_complete(self.async_send(self.AR[idx]["ws"],mes))
else:
self.myLoop.run_until_complete(self.async_send(self.cWS,mes))
def sendC(self,mes):
self.myLoop.run_until_complete(self.async_send(self.cWS,mes))
print("type:",type(mes))
def close(self,idx):
self.myLoop.run_until_complete(self.async_close(idx))
async def async_except_after(self):
print("hiraWSSV:async_except_after")
pass
async def connect(self,websocket):
self.cWS = websocket
self.AR.append({"ws":websocket})
await self.async_connect(websocket)
while True:
try:
message = await websocket.recv()
await self.async_message(websocket,message)
except Exception as e:
idx = self.searchWs(websocket)
await self.async_except(e,idx)
if idx >= 0:
self.AR.pop(idx)
try:
await websocket.close()
except Exception as e:
pass
await self.async_except_after()
break
async def main(self,host,port):
async with websockets.serve(self.connect, host, port):
print(f"WebSocket server is running on ws://{host}:{port}")
await asyncio.Future()
def RunForever(self,host,port):
print(f"
print(f" host; {host}")
print(f" port; {port}")
print("
try:
self.myLoop.run_until_complete(self.main(host, port))
finally:
self.myLoop.close()
こんな感じです。
ちなみに、、できをChatGPTに聞くと、、
完成度はかなり高いので、このままチューニングすれば本番運用レベルですよ!
とのこと。ホンマかいな!