CachéDBMS 2013.1では、CSPゲートウェイに、WebサーバーとHTML 5互換ブラウザ間のWebSocket接続用のHTML 5仕様のサポートが含まれるようになりました。 この機能は、Apache 2.2以降、およびWindows Server 2012の一部であるIIS 8.0で使用できます。
Apache 2.4は既にCaché2013.1に組み込まれているため、サンプルを実行します。
クライアント部分を実装するために、 ZENフレームワークが使用されましたが、 CSPテクノロジーまたはその他を使用して例を再作成できます。
それでは始めましょう。
理論
前述のとおり、CachéDBMSのサーバー側でWebSocketをサポートするためのすべての内部ロジックが引き継がれます。 プログラマは、 %CSP.WebSocketクラスから継承して独自のクラスを作成し、そのクラスのいくつかのメソッドをオーバーライドするだけです。
クラス%CSP.WebSocketのオブジェクトは、WebSocketプロトコルを使用したクライアントとサーバー間の通信のイベントハンドラーとして機能します。 すべてのWebSocketサーバーは%CSP.WebSocketを継承します。
%CSP.WebSocketクラスのメソッドとプロパティの詳細な説明は、クラスリファレンスにあります。
ここでは、そのうちのいくつかだけを簡単に説明します。
メソッド/プロパティ | 説明 |
---|---|
読む() | クライアントからデータを受信する |
書き込み() | クライアントにデータを送信する |
OnPreServer() | PreServerイベントハンドラー:WebSocketサーバーを起動する前に呼び出されます |
OnPostServer() | PostServerイベントハンドラー:WebSocketサーバーが停止すると呼び出されます |
サーバー() | WebSocketサーバー自体 |
EndServer() | Websocketサーバーを停止します |
出席する | 読み取り中にWebSocketサーバーが現在のデータフレームの最後に到達すると、プロパティの値はtrue(1)になります |
共有接続 | このプロパティは、クライアントとWebSocketサーバー間の情報交換が専用のCSPゲートウェイ接続を介して行われるか、共有接続のプール(まだ使用されていない)を介して行われるかを決定します |
練習する
これらすべてを実際に使用する方法の簡単な例を見てみましょう。
まず、 USER StudioでZENページ( demo.WebSocketクラス)を作成し、 %CSP.WebSocketクラスから継承します。
クラスdemo.WebSocket Extends ( %ZEN.Component.page 、 %CSP.WebSocket )
{
XData コンテンツ[ XMLNamespace = " www.intersystems.com/zen" ]
{
< page xmlns = " www.intersystems.com/zen" title = "" >
</ ページ >
}
}
JSONの操作をサポートするために、zenCSLM.jsファイルを含めます。
パラメーター JSINCLUDES = "zenCSLM.js" ;
WebSocketを介してクライアントを接続し、対応するイベントを処理するためのメソッドを実装します。
///このクライアントイベントが存在する場合、ページがロードされると発生します。
ClientMethod onloadHandler()[ 言語 = javascript]
{
ws = null;
url = ((window.location.protocol == 'https:' ) ? 'wss:' : 'ws:' ) + '//' + window.location.host + window.location.pathname;
wsCtor = window [ 'MozWebSocket' ] ? MozWebSocket : window [ 'WebSocket' ] ? WebSocket : null;
if (zenIsMissing(wsCtor))zenAlert( 'WebSocketはブラウザでサポートされていません!' );
}
ClientMethod start()[ 言語 = javascript]
{
if ( ! zenIsMissing(wsCtor)){
if (zenIsMissing(ws)){
ws = 新しい wsCtor(url);
ws.onopen = function (){
zenAlert( 'onopen \ n \ nreadyState:' 、ws.readyState、 '\ nbinaryType:' 、ws.binaryType、 '\ nbufferedAmount:' 、ws.bufferedAmount);
};
ws.onmessage = function (e){
zenAlert(e.data);
};
ws.onclose = function (e){
zenAlert( 'onclose \ n \ nwasClean:' 、e.wasClean、 '\ ncode:' 、e.code、 '\ nreason:' 、e.reason);
ws = null;
};
ws.onerror = function (e){
zenAlert( 'onerror' );
};
}
}
}
WebSocketサーバーの実装は同じページにあるため、接続文字列はプロトコルを除いて同一になります。 つまり、ZENページのURLの形式が
localhost:57772/csp/user/demo.WebSocket.cls
、次にWebSocketサーバーの場合は
ws://localhost:57772/csp/user/demo.WebSocket.cls
次に、ページに小さなインターフェイスを追加しましょう。サーバーにデータを接続、切断、送信するためのボタンがいくつかあります。
XData コンテンツ[ XMLNamespace = " www.intersystems.com/zen" ]
{
< page xmlns = " www.intersystems.com/zen" title = "" >
< text id = "txt" label = "送信するテキスト" value = "World" />
< button caption = " 1.Connect " onclick = "zenPage.start();" />
< button caption = "2.テキストを送信" onclick = "if(!zenIsMissing(ws))ws.send(zenGetProp( 'txt'、 'value'));" />
< button caption = "3.長い行を送信する" onclick = "zenPage.sendLongStr(100000);" />
< button caption = "4.Send JSON" onclick = "zenPage.sendJSON();" />
< button caption = "5.電源を切る" onclick = "if(!zenIsMissing(ws))ws.close();" />
</ ページ >
}
sendLongStrメソッドのコードは次のとおりです。
ClientMethod sendLongStr( N )[ 言語 = javascript]
{
if (zenIsMissing(ws)) return ;
var s = 'a' ;
for ( var i = 1 ; i < N; i ++ )s + = 'a' ;
ws.send(s);
}
sendJSONメソッドコード :
ClientMethod sendJSON()[ 言語 = javascript]
{
if (zenIsMissing(ws)) return ;
var obj = {
"firstName" : "Ivan" 、
"lastName" : "Ivanov" 、
「アドレス」 :{
"streetAddress" : "モスクワハイウェイ101、 apt。101" 、
「都市」 : 「レニングラード」 、
「 郵便番号 」 : 101101
}、
「phoneNumbers」 :[
「812 123-1234」 、
「916 123-4567」
]
};
ws.send(ZLM.jsonStringify(obj));
}
WebSocketサーバー自体を実装するときが来ました。 これを行うには、次のようにOnPreServer 、 OnPostServer、およびServerメソッドをオーバーライドします。
メソッド OnPreServer() As%Status
{
$ system .Processを実行し ます。 未定義 (2)
Set ^ tmp( $ Increment (^ tmp)、 "OnPreServer" )= ""
$$$ OKを終了OK
}
メソッド OnPostServer() As%Status
{
Set ^ tmp( $ Increment (^ tmp)、 "OnPostServer" )= ""
$$$ OKを終了OK
}
メソッド サーバー() As%ステータス
{
{
len = 32656に 設定
設定 データ = $ ZConvert (.. 読み取り ( 。Len , . Status )、 "I" 、 "UTF8" )
$$$ ISOK ( status ) {
data = "World"の 場合 {
。。Write ( $ ZConvert ( "Hello、" _ data _ "!" 、 "O" 、 "UTF8" ))
} ElseIf data = "bye" {
; WebSocketサーバーを強制的にシャットダウンし、無限ループを終了します
; oncloseはクライアントで動作します
Do .. EndServer ()
やめる
} その他 {
#Dim obj As %RegisteredObject = $$$ NULLOREF
Set ^ tmp = $ Increment (^ tmp)
; 文字列をオブジェクトに変換する
$$$ ISOK ( ##クラス ( %ZEN.Auxiliary.jsonProvider )。 %ConvertJSONToObject ( data ,,。 Obj )) {
; エラーがない場合、プロパティ値を保存します
^ tmp(^ tmp、 "Server" 、 "firstName" )= objを設定し ます。 firstName
^ tmp(^ tmp、 "Server" 、 "lastName" )= objを設定し ます。 lastName
^ tmp(^ tmp、 "Server" 、 "address.streetAddress" )= objを設定し ます。 住所 streetAddress
^ tmp(^ tmp、 "Server" 、 "address.city" )= objを設定し ます。 住所 市
^ tmp(^ tmp、 "Server" 、 "address.postalCode" )= objを設定し ます。 住所 postalCode
^ tmp(^ tmp、 "Server" 、 "phoneNumbers.1" )= objを設定し ます。 phoneNumbers 。 GetAt (1)
^ tmp(^ tmp、 "Server" 、 "phoneNumbers.2" )= objを設定し ます。 phoneNumbers 。 GetAt (2)
; 姓を変更
objを 設定し ます。 lastName = "Sidorov"
; 別の電話を追加
objを実行し ます。 phoneNumbers 。 挿入 ( "111 111-1111" )
; オブジェクトにさらに2つの新しいプロパティを追加します。
objを 設定し ます。 name = "Vasya"
objを 設定し ます。 street = "17 Mira Street"
; 変更されたオブジェクトを文字列に変換し、クライアントに送り返します
Do .. Write (.. Write2Str ( 。Obj ))
} その他 {
; 長い文字列を受信したときにデータを保存する
Set ^ tmp(^ tmp、 "Server" 、 "longStr" )= .. AtEnd _ ":" _ $ Length ( data )_ ":" _ len
}
}
} その他 {
終了 :( $$$ GETERRORCODE ( status )= $$$ CSPWebSocketClosed )
}
}
$$$ OKを終了OK
}
Write2Strユーティリティメソッドは、Writeコマンドによって出力されたデータを文字列にアセンブルするために使用されます。
ClassMethod Write2Str( ByRef obj ) As%String [ プライベート ]
{
{
tIO = $ IO 、 tXDEV = "| XDEV |"を設定します _ + $ Job
{
// $$$ IsUnicodeにはUTF-8を使用します
オープン tXDEV :( $ ZF (-6、 $$$ XSLTLibrary 、12): "" : "S" :/ HOSTNAME = "XSLT" :/ IOT = $ Select ( $$$ IsUnicode : "UTF8" 、1: " RAW " ):/ IBU = 16384:/ OBU = 16384)
tXDEVを 使用する
終了 : $$$ ISERR ( obj 。 %ToJSON (、 "aeloiwu" ))
//残りの出力をフラッシュします
書き込み * -3
//ここで文字列を読み戻します(最大長まで、32kまたは長い文字列の場合は約4MB)
s = ""を 設定
while (1) {
#Dim tChunk As %String
tChunk を読み取り ます :0
終了 : ' $長さ ( tChunk )
s = s _ tChunkを 設定
}
} while (0)
} キャッチ {}
tXDEVを 閉じ ます
tIOを 使用する
終了
}
クラスをコンパイルし(Ctrl + F7)、ブラウザーで表示するために開いたままにします(F5)。
ボタンを連続して押すと、^ tmpグローバルの内容は次のようになります。
^tmp=7
^tmp(1,"OnPreServer")=""
^tmp(2,"Server","longStr")="0:32656:32656"
^tmp(3,"Server","longStr")="0:32656:32656"
^tmp(4,"Server","longStr")="0:32656:32656"
^tmp(5,"Server","longStr")="1:2032:2032"
^tmp(6,"Server","address.city")=""
^tmp(6,"Server","address.postalCode")=101101
^tmp(6,"Server","address.streetAddress")=" ., 101, .101"
^tmp(6,"Server","firstName")=""
^tmp(6,"Server","lastName")=""
^tmp(6,"Server","phoneNumbers.1")="812 123-1234"
^tmp(6,"Server","phoneNumbers.2")="916 123-4567"
^tmp(7,"OnPostServer")=""
demo.WebSocketクラスのソースコードをダウンロードします 。