2021年6月10日木曜日

denoでwebSocketが自動切断されるまでの時間を調べる

webSocket接続は自動的に切れてしまう場合があるらしいです。
通信していない状況が一定時間継続すると切れてしまう場合は、その時間に達する前に通信するように仕組めば良いと思います。
まずは手元の環境で、どのぐらいの時間で切れるのかを確認するためのサンプルを作成しました。



結論から言うと、手元の環境では何時間経とうとも切れませんでした。

import { listenAndServe } from "https://deno.land/std/http/server.ts";
export async function httpサーバを起動(リクエスト処理: any){
const port = await 空いてるport番号を返す()
const server = listenAndServe({ port: port }, async (req)=> { リクエスト処理(req) });
console.log(`HTTP webserver running. Access it at: http://localhost:` + port + `/`)
ブラウザ起動(port)
}
function ブラウザ起動(port: number){
Deno.run({cmd:['cmd', '/C start http://localhost:'+port]})
}
async function 空いてるport番号を返す(): Promise<number>{
let pathBat = await 一時ファイルを作成('netstat -na | find "%~1"')
if(pathBat.match(/[  ]/)){
throw new Error('一時ファイルのPathにスペースが含まれています。\n'+pathBat+'\nDeno.runでは「"」の記号の前に「\\」が挿入されてしまうため、使用できません。')
}
for(let port=49152; port<=65535 ;port++){
const p = Deno.run({cmd:['cmd', '/C', 'chcp 65001 & '+pathBat+' ' + port], stdout:'piped'})
const o = await p.output()
const text = new TextDecoder().decode(o)
// console.log('text:\n'+text)
if(text.indexOf(':'+port)==-1){
Deno.remove(pathBat)
return port
}
}
throw new Error('throw from port num search')
}
async function 一時ファイルを作成(value:string){
const path = await Deno.makeTempFile({prefix: 'deno_tmp', suffix:'.bat'})
await Deno.writeTextFile(path, value)
return path
}
// --allow-run --allow-net --allow-read --allow-write
import { httpサーバを起動 } from './httpサーバを起動.ts'
import { リクエスト処理 } from './リクエスト処理.ts'
httpサーバを起動(リクエスト処理)
view raw main.ts hosted with ❤ by GitHub
import {
acceptWebSocket,
acceptable,
} from "https://deno.land/std/ws/mod.ts";
import { wsHandler } from './wsHandler.ts'
export function webSocket接続(request: any):void{
console.log('webSocket接続')
if(!acceptable(request)){return console.log('webSocket接続 not acceptable')}
acceptWebSocket({
conn: request.conn,
bufReader: request.r,
bufWriter: request.w,
headers: request.headers,
}).then(wsHandler);
}
import {
WebSocket,
isWebSocketCloseEvent,
} from "https://deno.land/std/ws/mod.ts";
export async function wsHandler(ws: WebSocket): Promise<void> {
const id = ++clientId;
clients.set(id, ws);
console.log(`[${id}]さんが入室しました`);
for await (const msg of ws) {
if (typeof msg === "string") {
ws.send(msg)
continue
} else if (isWebSocketCloseEvent(msg)) {
clients.delete(id);
break;
}
}
}
// 以下はexportしない(import先からコールできない)関数など。
const clients = new Map<number, WebSocket>();
let clientId = 0;
view raw wsHandler.ts hosted with ❤ by GitHub
import * as path from "https://deno.land/std@0.97.0/path/mod.ts"; // pathResolver
import { webSocket接続 } from './webSocket接続.ts'
export async function リクエスト処理(request: any){
if(request.method != 'GET'){return}
console.log('url:[' + request.url + ']')
let url = request.url
if(url=='/ws'){return webSocket接続(request)}
if(url=='/'){ url = './index.html' }
if(url.indexOf('/')==0){ url = '.' + url }
url = 絶対Pathに変換(url)
const ファイルの有無 = await fileExists(url)
if(!ファイルの有無){
return request.respond({ status: 404 })
}
const file = await Deno.open(url);
request.respond({
status: 200,
headers: new Headers({"content-type": 拡張子2contentType(url)}),
body: file
});
}
function pathResolver(meta: ImportMeta): (p: string) => string {
return (p) => path.fromFileUrl(new URL(p, meta.url))
}
const 絶対Pathに変換 = pathResolver(import.meta);
function 拡張子2contentType(url: string):string{
if(url.match(/\.htm(l?)$/)){return 'text/html'}
if(url.match(/\.css$/)){return 'text/css'}
return ''
}
async function fileExists(filePath: string): Promise<boolean> {
try {
await Deno.lstat(filePath);
return true;
} catch (err) {
if (err instanceof Deno.errors.NotFound) {
return false;
}
throw err;
}
}



実行中のcmd画面

サーバを終了させて接続が切れるとoncloseが動作して表示が変化するのは確認しました。


私が試した環境では、日付を跨いでも切断されることはありませんでした。


以下、webSocketの自動切断に関する情報。


webSocketの使い方について検索している最中に上記の情報を見かけて、「そういう問題があるなら対策しておこう」と思ったのですが、実際に切れてしまう環境でないと動作確認できないので、この件は新しい環境が入手できたらテストしてみます。

0 件のコメント:

コメントを投稿