新しいビルトイン WebSocketサーバー

相互接続が増しつつある世界においては、Webサイトや IoTアプリケーションがリアルタイムで更新されることが重要です。

相手に瞬時に情報を配信する方法として、サーバーとクライアントの間に双方向通信のチャンネルを提供する WebSocketプロトコルを使用することができます。v20 より、4D は WebSocketサーバーを作成するためのコマンドを提供します。

HDI: WebSocketサーバー

WebSocketサーバーを管理するために、4D は 2つの新しいビルトインクラスを提供します:

 

この機能を確認するために、簡単なチャットサーバーを作成してみましょう!

WebSocketサーバークラスを使用する前に、まずは 4D の Webサーバーを起動します。

4D.WebSocketServer

このクラスを使って、サーバーで発生するイベントを管理します。そのために、以下のような関数を持つユーザークラスを作成する必要があります:

  • onConnection(): 新しい接続がリクエストされたときに呼び出されます。
  • onOpen(): サーバー起動時に呼び出されます。
  • onTerminate(): サーバー終了時に呼び出されます。
  • onError(): エラー発生時に呼び出されます。

 

ここでは、WSServerHandlerクラスという名前のユーザークラスを作成します。

チャットの例では、最初に接続リクエストを管理する必要があります。onConnection() 関数は、Null を戻り値として返せば接続をキャンセルします。接続を許可する場合は、その後のメッセージの送受信を管理するためのオブジェクトを返します。サンプルでは、WSConnectionHandlerクラス (次のセクションで説明します) を返しています:

Class constructor

Function onConnection($wss : Object; $param : Object) : Object
        // VerifyAddress メソッドを呼び出して、リモートアドレスからの接続を許可するか判断します
	If (VerifyAddress($param.request.remoteAddress))
		// 接続を許可する場合
		// WSConnectionHandler オブジェクトが返されます
		// 4D はこのオブジェクトを使って、この接続に紐づけられた 
		// 4D.WebSocketConnection オブジェクトをインスタンス化します
		return cs.WSConnectionHandler.new() 
	Else 
		// 接続がキャンセルされます		
		return Null 
	End if 

WebSocketサーバーの開始と終了、そしてエラーのログを取りたいので、WSServerHandlerクラスに下の通り追加します:

Function onOpen($wss : Object; $param : Object)
LogFile("*** Server started")

Function onTerminate($wss : Object; $param : Object)
LogFile("*** Server closed")

Function onError($wss : Object; $param : Object)
LogFile("!!! Server error: "+$param.statusText)

4D.WebSocketConnection

このクラスを使って、特定の接続に関わるイベントを管理します。以下のような関数を持つユーザークラスを作成する必要があります:

  • onMessage(): この接続を介したメッセージを受信するたびに呼び出されます。
  • onOpen(): 4D.WebSocketConnection オブジェクトが作成されるときに呼び出されます。
  • onTerminate(): 4D.WebSocketConnection オブジェクトが終了されたときに呼び出されます。
  • onError(): エラー発生時に呼び出されます。

 

チャットの例では、WSConnectionHandlerクラスという名前のユーザークラスを作成します。

  • 接続時に、新しいユーザーが接続されたことを他のユーザーに知らせます。
  • 接続終了時に、ユーザーが切断されたことを他のユーザーに知らせます。
  • メッセージを受信すると、接続中の他のチャットクライアントにメッセージをブロードキャストします。

 

Function onMessage($ws : 4D.WebSocketConnection; $message : Object)
	// 他のチャットクライアントにメッセージをブロードキャストします	
	This.broadcast($ws;$message.data)

Function onOpen($ws : 4D.WebSocketConnection; $message : Object)
	// 接続したユーザーにメッセージを送信します
	$ws.send("チャットへようこそ!")	
	// 他のクライアントへは "新しいクライアントが接続しました" というメッセージを送信します
	This.broadcast($ws;"新しいクライアントが接続しました")

Function onTerminate($ws : 4D.WebSocketConnection; $message : Object)
	// "クライアントが切断されました" メッセージを他のクライアントに送信します
	This.broadcast($ws;"クライアントが切断されました")

Function broadcast($ws : 4D.WebSocketConnection; $message : Text)
	var $client:4D.WebSocketConnection
	// 他のチャットクライアントにメッセージをブロードキャストします
	For each ($client; $ws.wss.connections)
		// クライアントの id が発信者と同一でない場合にメッセージを送信します
		If ($client.id#$ws.id)
			$client.send($message)
		End if 
	End for each 

あとは、上記で作成したクラスを使ってウェブソケットサーバーを起動するだけです。ウェブソケットサーバーはワーカーで起動する必要があるので、CALL WORKERコマンドで新しいプロセスを作成し、その中で4D.WebSocketServerをインスタンス化します:

var $handler:cs.WSSHandler
$handler:=cs.WSServerHandler.new()

CALL WORKER("WebSocketServer"; Formula(WSS:=4D.WebSocketServer.new($handler)))
//WebSocketに変数(WSS)を割り当てると、その後にWSS.terminate()を呼び出すことができる。

作成されたウェブソケットサーバは、ワーカーが強制終了されるか .terminate() 関数が呼ばれるまで存在します。

CALL WORKER("WebSocketServer"; Formula(WSS.terminate()))

クライアント側

HTML と Javascript でチャットインターフェースを作成するコードの例です:

このコードは、HTTPポート 80 のローカルWebサーバーで動作するように設計されています (18行目: const urlwss=”ws://127.0.0.1:80/”;)。

上の HDI とドキュメントにて、この機能の詳細を確認してください!

Fabrice Mainguené
- Product Owner -Fabrice Mainguenéは、2016年11月に4D Programチームに参加しました。プロダクトオーナーとして、彼はユーザーストーリーを書き、それを機能仕様に変換する役割を担っています。CNAMでコンピュータサイエンスの学士号を取得した後、FabriceはWindev開発者として小さなソフトウェア出版社に入社しました。その後、彼は産業および貿易分野のさまざまな企業で、Windev および Web 開発者として、また新機能の技術アドバイザーとして働きました。