ブラウザから直接TCP・UDPで送受信する「Direct Sockets API」という仕組みが議論されています。
実験段階ですが、Chromeでは起動時にオプションを付けることでこの機能を有効にできます。今回はTCPの方で簡単に動作を見てみます。
Direct Sockets API
Direct Sockets APIは、TCP・UDPで直接送受信可能にするAPIです。既存のアプリケーションプロトコル(SSHやIRC)、P2Pのような機能を実現可能になります。
もちろんセキュリティ上の問題もあるので、Chromeでは現状デフォルトでは有効になっていない機能です。
セキュリティ面についてはだいぶGithubリポジトリで議論されておりますので目を通すと良いでしょう。ローカルネットワークへの通信やSame-Origin-Policy(CORS)回避の話が上がっていますが、今回は細かくは紹介しません。
その他、意見がある場合はコメントすることもできます。
github.com
試してみる
Chromeでは実験的に実装されています。おそらくまだ実装途中ですので、今後変わる可能性は高いです。
今回は、現在時点のChrome Canaryで動作確認しています。
クライアント側準備
起動時にオプションが必要です。
Chrome 99 では次の起動オプションをつけて、Chromeを起動します (現在の起動コマンドは、chrome:version から確認できます)
- --enable-blink-features=DirectSockets
- --enable-features=DirectSockets
- --restricted-api-origins=https://asnokaze.com
サーバ側準備
有効にするページ(上記 --restricted-api-origins で指定したページ)で、次のレスポンスヘッダをつけます
- Cross-Origin-Embedder-Policy: require-corp
- Cross-Origin-Opener-Policy: same-origin
- Permissions-Policy: direct-sockets=(self)
なお、TCPサーバ特定ポートで接続を受け付けるために、下記のコマンドを実行して123番ポートでリッスンしておきます。(well-knownポートが使用できるか確認するために、123番を使用)
$ while true; do ( echo "Hello from server" ) | sudo nc -l 123; done
つなぐ
Webページを開いたら、今回はデベロッパーツールで以下に示すスクリプトを実行します。このスクリプトでは
すると、ダイアログが出るので接続先を入力します。(現状は任意のサーバ・任意のポートが指定可能...)
const options = { remoteAddress: 'asnokaze.com', remotePort: 123 }; navigator.openTCPSocket(options).then(tcpSocket => { readableStream = tcpSocket.readable; writableStream = tcpSocket.writable; const defaultWriter = writableStream.getWriter(); defaultWriter.ready.then(() => { return defaultWriter.write(str2ab("Hello from chrome")); }) const defaultReader = readableStream.getReader() defaultReader.read().then( ({done, value}) => { console.log(ab2str(value)); }) }) function str2ab(str) { var buf = new ArrayBuffer(str.length); var bufView = new Uint8Array(buf); for (var i=0, strLen=str.length; i < strLen; i++) { bufView[i] = str.charCodeAt(i); } return buf; } function ab2str(buf) { return String.fromCharCode.apply(null, new Uint8Array(buf)); }
サーバ側
クライアントからのメッセージが表示されました
$ while true; do ( echo "Hello from server" ) | sudo nc -l 123; done Hello from chrome
クライアント側
サーバからのメッセージが表示されました