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クラスのソースコードをダウンロードします

Source: https://habr.com/ru/post/J181113/


All Articles