CachéDBMS 2013.1の新機能:ネイティブWebSocketサポート

前回の記事で 、通常のソケットの上にこのプロトコルを独自に実装したサーバーの例を使用して、WebSocketの操作について既に説明しました。



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サーバー自体を実装するときが来ました。 これを行うには、次のようにOnPreServerOnPostServer、および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クラスのソースコードをダウンロードします



All Articles