チュートリアル: サブプロトコルを使用して、WebSocket クライアント間でメッセージを発行およびサブスクライブする
- [アーティクル]
-
-
チャット アプリの構築に関するチュートリアルでは、WebSocket API を使って Azure Web PubSub でデータを送受信する方法について説明しました。 クライアントがサービスと通信する際に、プロトコルが必要ないことが分かります。 たとえば、WebSocket.send()
を使うと任意の種類のデータを送信でき、サーバーはそれをそのまま受信します。 WebSocket API プロセスは使いやすいですが、機能が制限されています。 たとえば、サーバーにイベントを送信するときにイベント名を指定したり、自分のサーバーに送信する代わりに他のクライアントにメッセージを発行したりすることはできません。 このチュートリアルでは、サブプロトコルを使ってクライアントの機能を拡張する方法について説明します。
このチュートリアルでは、次の作業を行う方法について説明します。
- Azure Web PubSub サービス インスタンスを作成する
- 完全な URL を生成して WebSocket 接続を確立する
- サブプロトコルを使用して WebSocket クライアント間でメッセージを発行する
Azure サブスクリプションをお持ちでない場合は、開始する前に Azure 無料アカウントを作成してください。
前提条件
- このセットアップには、Azure CLI のバージョン 2.22.0 以降が必要です。 Azure Cloud Shell を使用している場合は、最新バージョンが既にインストールされています。
重要
この記事では、デモ目的でのみ生の接続文字列が表示されます。
接続文字列には、アプリケーションが Azure Web PubSub サービスにアクセスするために必要な認可情報が含まれています。 接続文字列内のアクセス キーは、サービスのルート パスワードに似ています。 運用環境では、常にアクセス キーを保護してください。 Azure Key Vault を使ってキーの管理とローテーションを安全に行い、WebPubSubServiceClient
を使って接続をセキュリティ保護します。
アクセス キーを他のユーザーに配布したり、ハードコーディングしたり、他のユーザーがアクセスできるプレーンテキストで保存したりしないでください。 キーが侵害された可能性があると思われる場合は、キーをローテーションしてください。
Azure Web PubSub インスタンスを作成する
リソース グループを作成する
リソース グループとは、Azure リソースのデプロイと管理に使用する論理コンテナーです。 az group create コマンドを使用して、myResourceGroup
という名前のリソース グループを eastus
の場所に作成します。
az group create --name myResourceGroup --location EastUS
Web PubSub インスタンスを作成する
az extension add を実行して、webpubsub 拡張機能をインストールするか、最新バージョンにアップグレードします。
az extension add --upgrade --name webpubsub
Azure CLI の az webpubsub create コマンドを使用して、作成したリソース グループに Web PubSub を作成します。 次のコマンドは、EastUS のリソース グループ myResourceGroup の下に "無料の" Web PubSub リソースを作成します。
重要
Web PubSub リソースには、それぞれ一意の名前を付ける必要があります。 次の例では、<your-unique-resource-name> をお使いの Web PubSub の名前に置き換えてください。
az webpubsub create --name "<your-unique-resource-name>" --resource-group "myResourceGroup" --location "EastUS" --sku Free_F1
このコマンドの出力では、新しく作成したリソースのプロパティが表示されます。 次の 2 つのプロパティをメモしておきます。
- Resource Name: 上記の
--name
パラメーターに指定した名前です。
- hostName: この例では、ホスト名は
<your-unique-resource-name>.webpubsub.azure.com/
です。
この時点で、お使いの Azure アカウントのみが、この新しいリソースで任意の操作を実行することを許可されています。
将来使用するために ConnectionString を取得する
この記事では、デモ目的でのみ生の接続文字列が表示されます。 運用環境では、常にアクセス キーを保護してください。 Azure Key Vault を使ってキーの管理とローテーションを安全に行い、WebPubSubServiceClient
を使って接続をセキュリティ保護します。
Azure CLI の az webpubsub key コマンドを使用して、サービスの ConnectionString を取得します。 プレースホルダー <your-unique-resource-name>
を実際の Azure Web PubSub インスタンスの名前に置き換えます。
az webpubsub key show --resource-group myResourceGroup --name <your-unique-resource-name> --query primaryConnectionString --output tsv
後で使うために接続文字列をコピーします。
フェッチされた ConnectionString をコピーしておき、このチュートリアルで後ほど <connection_string>
の値としてそれを使います。
プロジェクトのセットアップ
前提条件
サブプロトコルの使用
クライアントは、特定のサブプロトコルを使用して WebSocket 接続を開始できます。 Azure Web PubSub サービスでは、json.webpubsub.azure.v1
と呼ばれるサブプロトコルがサポートされています。これにより、クライアントはアップストリーム サーバーにラウンド トリップすることなく、発行/サブスクライブを直接実行できます。 サブプロトコルの詳細については、「Azure Web PubSub でサポートされる JSON WebSocket サブプロトコル」をご覧ください。
他のプロトコル名を使用すると、それはサービスによって無視され、接続イベント ハンドラー内のサーバーにパススルーされます。そのため、独自のプロトコルを構築することができます。
それでは、json.webpubsub.azure.v1
サブプロトコルを使用して Web アプリケーションを作成しましょう。
依存関係のインストール
mkdir logstream
cd logstream
dotnet new web
dotnet add package Microsoft.Extensions.Azure
dotnet add package Azure.Messaging.WebPubSub
mkdir logstream
cd logstream
npm init -y
npm install --save express
npm install --save ws
npm install --save node-fetch
npm install --save @azure/web-pubsub
mkdir logstream
cd logstream
# Create venv
python -m venv env
# Active venv
source ./env/bin/activate
pip install azure-messaging-webpubsubservice
Javalin Web フレームワークを使って Web ページをホストします。
まず、Maven を使用して新しいアプリ logstream-webserver
を作成し、logstream-webserver フォルダーに切り替えます。
mvn archetype:generate --define interactiveMode=n --define groupId=com.webpubsub.tutorial --define artifactId=logstream-webserver --define archetypeArtifactId=maven-archetype-quickstart --define archetypeVersion=1.4
cd logstream-webserver
Azure Web PubSub SDK とjavalin
Web フレームワークの依存関係を pom.xml
の dependencies
ノードに追加しましょう。
javalin
: Java 用の単純な Web フレームワーク
slf4j-simple
: Java 用ロガー
azure-messaging-webpubsub
: Azure Web PubSub を使用するためのサービス クライアント SDK
<dependency>
<groupId>com.azure</groupId>
<artifactId>azure-messaging-webpubsub</artifactId>
<version>1.0.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/io.javalin/javalin -->
<dependency>
<groupId>io.javalin</groupId>
<artifactId>javalin</artifactId>
<version>3.13.6</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.7.30</version>
</dependency>
/negotiate
API と Web ページをホストするサーバー側を作成します。
下のコードを使用して Program.cs
を更新します。
AddAzureClients
を使ってサービス クライアントを追加し、構成から接続文字列を読み取ります。
- 静的ファイルをサポートするために、
app.Run();
の前に app.UseStaticFiles();
を追加します。
app.MapGet
を更新して、/negotiate
要求を持つクライアント アクセス トークンを生成します。
using Azure.Messaging.WebPubSub;
using Microsoft.Extensions.Azure;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddAzureClients(s =>
{
s.AddWebPubSubServiceClient(builder.Configuration["Azure:WebPubSub:ConnectionString"], "stream");
});
var app = builder.Build();
app.UseStaticFiles();
app.MapGet("/negotiate", async context =>
{
var service = context.RequestServices.GetRequiredService<WebPubSubServiceClient>();
var response = new
{
url = service.GetClientAccessUri(roles: new string[] { "webpubsub.sendToGroup.stream", "webpubsub.joinLeaveGroup.stream" }).AbsoluteUri
};
await context.Response.WriteAsJsonAsync(response);
});
app.Run();
server.js
を作成し、以下のコードを追加します。
const express = require('express');
const { WebPubSubServiceClient } = require('@azure/web-pubsub');
let service = new WebPubSubServiceClient(process.env.WebPubSubConnectionString, 'stream');
const app = express();
app.get('/negotiate', async (req, res) => {
let token = await service.getClientAccessToken({
roles: ['webpubsub.sendToGroup.stream', 'webpubsub.joinLeaveGroup.stream']
});
res.send({
url: token.url
});
});
app.use(express.static('public'));
app.listen(8080, () => console.log('server started'));
server.py
を作成し、/negotiate
API と Web ページをホストします。
import json
import sys
from http.server import HTTPServer, SimpleHTTPRequestHandler
from azure.messaging.webpubsubservice import WebPubSubServiceClient
service = WebPubSubServiceClient.from_connection_string(sys.argv[1], hub='stream')
class Request(SimpleHTTPRequestHandler):
def do_GET(self):
if self.path == '/':
self.path = 'public/index.html'
return SimpleHTTPRequestHandler.do_GET(self)
elif self.path == '/negotiate':
roles = ['webpubsub.sendToGroup.stream',
'webpubsub.joinLeaveGroup.stream']
token = service.get_client_access_token(roles=roles)
self.send_response(200)
self.send_header('Content-Type', 'application/json')
self.end_headers()
self.wfile.write(json.dumps({
'url': token['url']
}).encode())
if __name__ == '__main__':
if len(sys.argv) != 2:
print('Usage: python server.py <connection-string>')
exit(1)
server = HTTPServer(('localhost', 8080), Request)
print('server started')
server.serve_forever()
/src/main/java/com/webpubsub/tutorial ディレクトリに移動し、App.java ファイルをエディタで開き、Javalin.create
を使用して静的ファイルを提供します。
package com.webpubsub.tutorial;
import com.azure.messaging.webpubsub.WebPubSubServiceClient;
import com.azure.messaging.webpubsub.WebPubSubServiceClientBuilder;
import com.azure.messaging.webpubsub.models.GetClientAccessTokenOptions;
import com.azure.messaging.webpubsub.models.WebPubSubClientAccessToken;
import io.javalin.Javalin;
public class App {
public static void main(String[] args) {
if (args.length != 1) {
System.out.println("Expecting 1 arguments: <connection-string>");
return;
}
// create the service client
WebPubSubServiceClient service = new WebPubSubServiceClientBuilder()
.connectionString(args[0])
.hub("chat")
.buildClient();
// start a server
Javalin app = Javalin.create(config -> {
config.addStaticFiles("public");
}).start(8080);
// Handle the negotiate request and return the token to the client
app.get("/negotiate", ctx -> {
GetClientAccessTokenOptions option = new GetClientAccessTokenOptions();
option.addRole("webpubsub.sendToGroup.stream");
option.addRole("webpubsub.joinLeaveGroup.stream");
WebPubSubClientAccessToken token = service.getClientAccessToken(option);
// return JSON string
ctx.result("{\"url\":\"" + token.getUrl() + "\"}");
return;
});
}
}
設定によっては、pom.xml で明示的に言語レベルを Java 8 に設定することが必要な場合があります。 次のスニペットを追加します。
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
Web ページの作成
以下のコンテンツを含む HTML ページを作成し、wwwroot/index.html
として保存します。
以下のコンテンツを含む HTML ページを作成し、public/index.html
として保存します。
以下のコンテンツを含む HTML ページを作成し、public/index.html
として保存します。
以下の内容の HTML ページを作成し /src/main/resources/public/index.html に保存します。
<html>
<body>
<div id="output"></div>
<script>
(async function () {
let res = await fetch('/negotiate')
let data = await res.json();
let ws = new WebSocket(data.url, 'json.webpubsub.azure.v1');
ws.onopen = () => {
console.log('connected');
};
let output = document.querySelector('#output');
ws.onmessage = event => {
let d = document.createElement('p');
d.innerText = event.data;
output.appendChild(d);
};
})();
</script>
</body>
</html>
上記のコードを使うと、サービスへの接続が行われ、受信したメッセージがページに出力されます。 主な変更は、WebSocket 接続の作成時にサブプロトコルを指定することです。
サーバーを実行する
.NET Core 用の Secret Manager ツールを使用して接続文字列を設定します。 <connection_string>
を、前の手順でフェッチされたものに置き換えて下のコマンドを実行し、ブラウザで http://localhost:5000/index.html を開きます。
dotnet user-secrets init
dotnet user-secrets set Azure:WebPubSub:ConnectionString "<connection-string>"
dotnet run
<connection-string>
を、前の手順でフェッチされた ConnectionString に置き換えて下のコマンドを実行し、ブラウザで http://localhost:8080 を開きます。
export WebPubSubConnectionString="<connection-string>"
node server
<connection-string>
を、前の手順でフェッチされた ConnectionString に置き換えて下のコマンドを実行し、ブラウザで http://localhost:8080 を開きます。
python server.py "<connection-string>"
<connection-string>
を、前の手順でフェッチされた ConnectionString に置き換えて下のコマンドを実行し、ブラウザで http://localhost:8080 を開きます。
mvn compile & mvn package & mvn exec:java -Dexec.mainClass="com.webpubsub.tutorial.App" -Dexec.cleanupDaemonThreads=false -Dexec.args="'<connection_string>'"
Chrome をお使いの場合は、F12 を押すか、右クリック -> [検証] -> [デベロッパー ツール] を選んで、[ネットワーク] タブを選びます。Web ページを読み込むと、WebSocket 接続が確立されていることを確認できます。 WebSocket 接続を選んで検査します。次の connected
イベント メッセージをクライアントが受信していることを確認できます。 このクライアントに connectionId
を生成できることが分かります。
{"type":"system","event":"connected","userId":null,"connectionId":"<the_connection_id>"}
サブプロトコルを使用すると、接続が connected
のときに接続のメタデータを取得できます。
クライアントはプレーンテキストではなく JSON メッセージを受信するようになりました。 JSON メッセージには、メッセージの種類やソースなど、より詳細な情報が含まれています。 そのため、この情報を使用して、メッセージに対してより多くの処理を実行できます (たとえば、別のソースからの場合は、別のスタイルでメッセージを表示するなど)。これは、後のセクションで説明します。
クライアントからメッセージを発行する
チャット アプリのビルドに関するチュートリアルでは、クライアントが WebSocket 接続を介して Web PubSub サービスにメッセージを送信すると、サービスによってサーバー側でユーザー イベントがトリガーされます。 サブプロトコルを使って JSON メッセージを送信すると、クライアントの機能が向上します。 たとえば、Web PubSub サービスを介してクライアントから他のクライアントに直接メッセージを発行できます。
これは、リアルタイムで大量のデータを他のクライアントにストリーミングする場合に便利です。 この機能を使用し、コンソール ログをリアルタイムでブラウザーにストリーミングできる、ログ ストリーミング アプリケーションを構築しましょう。
ストリーミング プログラムの作成
stream
プログラムを作成します。
mkdir stream
cd stream
dotnet new console
次の内容を使用して Program.cs
を更新します。
using System;
using System.Net.Http;
using System.Net.WebSockets;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
namespace stream
{
class Program
{
private static readonly HttpClient http = new HttpClient();
static async Task Main(string[] args)
{
// Get client url from remote
var stream = await http.GetStreamAsync("http://localhost:5000/negotiate");
var url = (await JsonSerializer.DeserializeAsync<ClientToken>(stream)).url;
var client = new ClientWebSocket();
client.Options.AddSubProtocol("json.webpubsub.azure.v1");
await client.ConnectAsync(new Uri(url), default);
Console.WriteLine("Connected.");
var streaming = Console.ReadLine();
while (streaming != null)
{
if (!string.IsNullOrEmpty(streaming))
{
var message = JsonSerializer.Serialize(new
{
type = "sendToGroup",
group = "stream",
data = streaming + Environment.NewLine,
});
Console.WriteLine("Sending " + message);
await client.SendAsync(Encoding.UTF8.GetBytes(message), WebSocketMessageType.Text, true, default);
}
streaming = Console.ReadLine();
}
await client.CloseAsync(WebSocketCloseStatus.NormalClosure, null, default);
}
private sealed class ClientToken
{
public string url { get; set; }
}
}
}
次の内容を使用して stream.js
を作成します。
const WebSocket = require('ws');
const fetch = (...args) => import('node-fetch').then(({default: fetch}) => fetch(...args));
async function main() {
let res = await fetch(`http://localhost:8080/negotiate`);
let data = await res.json();
let ws = new WebSocket(data.url, 'json.webpubsub.azure.v1');
let ackId = 0;
ws.on('open', () => {
process.stdin.on('data', data => {
ws.send(JSON.stringify({
type: 'sendToGroup',
group: 'stream',
ackId: ++ackId,
dataType: 'text',
data: data.toString()
}));
});
});
ws.on('message', data => console.log("Received: %s", data));
process.stdin.on('close', () => ws.close());
}
main();
上記のコードは、サービスへの WebSocket 接続を作成し、データを受信するたびに ws.send()
を使用してそのデータを発行します。 他のグループに発行するには、type
を sendToGroup
に設定し、メッセージでグループ名を指定します。
stream
プログラム用の別の bash ウィンドウを開き、websockets
依存関係をインストールします。
mkdir stream
cd stream
# Create venv
python -m venv env
# Active venv
source ./env/bin/activate
pip install websockets
次の内容を使用して stream.py
を作成します。
import asyncio
import sys
import threading
import time
import websockets
import requests
import json
async def connect(url):
async with websockets.connect(url, subprotocols=['json.webpubsub.azure.v1']) as ws:
print('connected')
id = 1
while True:
data = input()
payload = {
'type': 'sendToGroup',
'group': 'stream',
'dataType': 'text',
'data': str(data + '\n'),
'ackId': id
}
id = id + 1
await ws.send(json.dumps(payload))
await ws.recv()
if __name__ == '__main__':
res = requests.get('http://localhost:8080/negotiate').json()
try:
asyncio.get_event_loop().run_until_complete(connect(res['url']))
except KeyboardInterrupt:
pass
上記のコードは、サービスへの WebSocket 接続を作成し、データを受信するたびに ws.send()
を使用してそのデータを発行します。 他のグループに発行するには、type
を sendToGroup
に設定し、メッセージでグループ名を指定します。
別のターミナルを使用してルート フォルダーに戻り、ストリーミング コンソール アプリ logstream-streaming
を作成して、logstream-streaming フォルダーに切り替えます。
mvn archetype:generate --define interactiveMode=n --define groupId=com.webpubsub.quickstart --define artifactId=logstream-streaming --define archetypeArtifactId=maven-archetype-quickstart --define archetypeVersion=1.4
cd logstream-streaming
pom.xml
の dependencies
ノードに HttpClient の依存関係を追加してみましょう。
<!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.13</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.9</version>
</dependency>
ここで、WebSocket を使用してサービスに接続します。 /src/main/java/com/webpubsub/quickstart ディレクトリに移動し、エディタで App.java ファイルをオープンして、下のコードに置き換えます。
package com.webpubsub.quickstart;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.http.WebSocket;
import java.util.concurrent.CompletionStage;
import com.google.gson.Gson;
public class App
{
public static void main( String[] args ) throws IOException, InterruptedException
{
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("http://localhost:8080/negotiate"))
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
Gson gson = new Gson();
String url = gson.fromJson(response.body(), Entity.class).url;
WebSocket ws = HttpClient.newHttpClient().newWebSocketBuilder().subprotocols("json.webpubsub.azure.v1")
.buildAsync(URI.create(url), new WebSocketClient()).join();
int id = 0;
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
String streaming = reader.readLine();
App app = new App();
while (streaming != null && !streaming.isEmpty()){
String frame = gson.toJson(app.new GroupMessage(streaming + "\n", ++id));
System.out.println("Sending: " + frame);
ws.sendText(frame, true);
streaming = reader.readLine();
}
}
private class GroupMessage{
public String data;
public int ackId;
public final String type = "sendToGroup";
public final String group = "stream";
GroupMessage(String data, int ackId){
this.data = data;
this.ackId = ackId;
}
}
private static final class WebSocketClient implements WebSocket.Listener {
private WebSocketClient() {
}
@Override
public void onOpen(WebSocket webSocket) {
System.out.println("onOpen using subprotocol " + webSocket.getSubprotocol());
WebSocket.Listener.super.onOpen(webSocket);
}
@Override
public CompletionStage<?> onText(WebSocket webSocket, CharSequence data, boolean last) {
System.out.println("onText received " + data);
return WebSocket.Listener.super.onText(webSocket, data, last);
}
@Override
public void onError(WebSocket webSocket, Throwable error) {
System.out.println("Bad day! " + webSocket.toString());
WebSocket.Listener.super.onError(webSocket, error);
}
}
private static final class Entity {
public String url;
}
}
- pom.xml ファイルが格納されているディレクトリに移動し、次のコマンドを使用してプロジェクトを実行します
mvn compile & mvn package & mvn exec:java -Dexec.mainClass="com.webpubsub.quickstart.App" -Dexec.cleanupDaemonThreads=false
ここでは、"group" という新しい概念があることがわかります。 グループは、接続のグループにメッセージを発行できる、ハブの論理的な概念です。 ハブでは、複数のグループを使用でき、1 つのクライアントは同時に複数のグループをサブスクライブできます。 サブプロトコルを使用する場合には、ハブ全体にブロードキャストするのではなく、グループにのみ発行できます。 用語の詳細については、「基本的な概念」をご覧ください。
ここではグループを使用するため、ws.onopen
コールバック内で WebSocket 接続を確立する際に、Web ページ index.html
を更新し、グループに参加する必要もあります。
let ackId = 0;
ws.onopen = () => {
console.log('connected');
ws.send(JSON.stringify({
type: 'joinGroup',
group: 'stream',
ackId: ++ackId
}));
};
クライアントがグループに参加しているのを確認するには、joinGroup
型のメッセージを送信します。
また、ws.onmessage
コールバック ロジックを少々更新して、JSON 応答を解析し、stream
グループからのメッセージのみを出力するようにして、ライブ ストリーム プリンターとして機能させます。
ws.onmessage = event => {
let message = JSON.parse(event.data);
if (message.type === 'message' && message.group === 'stream') {
let d = document.createElement('span');
d.innerText = message.data;
output.appendChild(d);
window.scrollTo(0, document.body.scrollHeight);
}
};
セキュリティ上の理由から、既定では、クライアントは、それ自体でグループに発行したり、またはグループをサブスクライブすることはできません。 そのため、お気づきのように、トークンを生成するときに roles
をクライアントに設定します。
Startup.cs
のGenerateClientAccessUri
で、roles
を下のように設定します。
service.GenerateClientAccessUri(roles: new string[] { "webpubsub.sendToGroup.stream", "webpubsub.joinLeaveGroup.stream" })
server.js
のgetClientAccessToken
で、roles
を下のように追加します。
app.get('/negotiate', async (req, res) => {
let token = await service.getClientAccessToken({
roles: ['webpubsub.sendToGroup.stream', 'webpubsub.joinLeaveGroup.stream']
});
...
});
アクセス トークン生成プロセスの間に、server.py
で適切なロールをクライアントに設定します。
roles = ['webpubsub.sendToGroup.stream',
'webpubsub.joinLeaveGroup.stream']
token = service.get_client_access_token(roles=roles)
アクセス トークン生成プロセスの間に、App.java
で適切なロールをクライアントに設定します。
GetClientAccessTokenOptions option = new GetClientAccessTokenOptions();
option.addRole("webpubsub.sendToGroup.stream");
option.addRole("webpubsub.joinLeaveGroup.stream");
WebPubSubClientAccessToken token = service.getClientAccessToken(option);
最後に、適切に表示されるようにするため、index.html
にスタイルを適用します。
<html>
<head>
<style>
#output {
white-space: pre;
font-family: monospace;
}
</style>
</head>
次に、下のコードを実行し、任意のテキストを入力すると、それがブラウザーにリアルタイムで表示されます。
ls -R | dotnet run
# Or call `dir /s /b | dotnet run` when you are using CMD under Windows
または速度を低下させ、データがリアル タイムでブラウザーにストリーミングされるのを確認します。
for i in $(ls -R); do echo $i; sleep 0.1; done | dotnet run
このチュートリアルの完成したコード サンプルは、こちらにあります。
node stream
または、このアプリを使用し、別のコンソール アプリからの出力をパイプしてブラウザーにストリーミングすることもできます。 例:
ls -R | node stream
# Or call `dir /s /b | node stream` when you are using CMD under Windows
または速度を低下させ、データがリアル タイムでブラウザーにストリーミングされるのを確認します。
for i in $(ls -R); do echo $i; sleep 0.1; done | node stream
このチュートリアルの完成したコード サンプルは、こちらにあります。
次に、python stream.py
を実行し、任意のテキストを入力すると、それがブラウザーにリアルタイムで表示されます。
または、このアプリを使用し、別のコンソール アプリからの出力をパイプしてブラウザーにストリーミングすることもできます。 例:
ls -R | python stream.py
# Or call `dir /s /b | python stream.py` when you are using CMD under Windows
または速度を低下させ、データがリアル タイムでブラウザーにストリーミングされるのを確認します。
for i in $(ls -R); do echo $i; sleep 0.1; done | python stream.py
このチュートリアルの完成したコード サンプルは、こちらにあります。
次に、下のコードを実行し、任意のテキストを入力ですると、それがブラウザーにリアルタイムで表示されます。
mvn compile & mvn package & mvn exec:java -Dexec.mainClass="com.webpubsub.quickstart.App" -Dexec.cleanupDaemonThreads=false
このチュートリアルの完全なコード サンプルは、こちらにあります。
次のステップ
このチュートリアルでは、Web PubSub サービスに接続する方法と、サブプロトコルを使用して、接続されているクライアントにメッセージを発行する方法に関する基本的な考え方を説明しています。
サービスの使用方法の詳細については、他のチュートリアルを参照してください。