TCP接続の受信を処理する TCPListener クラス

4D 20 R8 では、TCPConnectionクラスを導入し、リモートサーバーへの TCP接続を開始できるようになりました。4D v20 R9 では、TCPListenerクラスが導入され、4D で直接 TCP接続の着信を処理し、TCPサーバーを構築できるようになりました。

TCPConnection と TCPListenerクラスがあれば、クライアント側とサーバー側の両方で、TCP通信を完全にコントロールすることができます。

この 2つのクラスの使い方を説明します。

HDI: TCPListenerクラス

この記事を読み進める前に、TCPConnectionクラスに関する以前のブログ記事をチェックし、基礎を理解することを強くお勧めします。

 

TCPListenerクラスと TCPConnectionクラスの関係図

接続クラスの定義

前の例で使用した ConnectionToTheServerクラスをモデルにして、ServerSideConnection という新しいクラスを作成します。実装する主なコールバックの内訳は以下のとおりです:

Class constructor()

// 接続に成功したときに呼び出されるコールバック
Function onConnection($connection : 4D.TCPConnection; $event : 4D.TCPEvent) 
	ALERT("接続しました") 

// 接続が正常に解除されたときに呼び出されるコールバック
Function onShutdown($connection : 4D.TCPConnection; $event : 4D.TCPEvent) 
	ALERT("接続が解除されました") 

// データを受信したときに呼び出されるコールバック。この簡単なサーバーは常に、ユーザーに表示するテキストを返信します
Function onData($connection : 4D.TCPConnection; $event : 4D.TCPEvent) 
	ALERT(BLOB to text($event.data; UTF8 text without length)) 

// 接続が予定外に解除されたときに呼び出されるコールバック
Function onError($connection : 4D.TCPConnection; $event : 4D.TCPEvent) 
	ALERT("接続エラー")

このクラスは、主要な TCPイベントに反応する単純なシェルです。

リスナークラスの設定

次は、特定のポートで待ち受け、接続の着信を受け付ける ServerListenerクラスを作成しましょう:

property listener:4D.TCPListener

shared singleton Class constructor()

// 引数で指定したポートをリッスンする TCPListener を作成します
shared Function startListening($port:integer)
	This.listener:=4D.TCPListener.new($port, This)

// リスナーを停止します
shared Function stopListening()
	This.listener.terminate()

// 接続を受信すると呼び出されるコールバック	
Function onConnection($listener : 4D.TCPListener; $event : 4D.TCPEvent)->$result
	
	ALERT("Listener: onConnection")
	if ($event.IP = "a good IP address")
		$result:=cs.ServerSideConnection.new()
	else
		$result := null
	end if
	
// すでに別のアプリケーションによって使用されているなど、エラーによりポートをリッスンできない場合に呼び出されるコールバック
Function onError($listener : 4D.TCPListener; $event : 4D.TCPEvent)
	
	ALERT("Listener: onError")

リスナーを開始するには:

cs.ServerListener.me.startListening($port)

クライアントが接続を試みるたびに、onConnection関数がトリガーされます。接続を受け入れる場合はServerSideConnectionオブジェクトを返し、拒否する場合は NULL を返します。いったん接続が許可されると、対応するTCPConnectionコールバックが開始され、他のクライアントと同じように接続を処理することができます。

新規接続のリッスンを停止するには:

cs.ServerListener.me.stopListening()

注記: アクティブな接続は、手動で閉じるまで残ります。

統一されたクラス構造 = 簡素化されたコード

この設計の主な利点は、クライアント接続とサーバー接続の両方に同じ TCPConnectionクラスが使われることです。この対称性により、実装が単純化され、コードの再利用が促進されます。

まとめ

4D v20 R9 に TCPListenerクラスが追加されたことで、4D で堅牢な TCPサーバーを作成できるようになりました。TCPConnection と組み合わせることで、新しいツールは、双方向の TCP通信を扱うための完全なフレームワークを提供します。

質問やフィードバックがあれば、遠慮なく4Dフォーラムにお寄せください。

Nicolas Brachfogel
- プロダクトオーナー & シニアデベロッパー - Nicolas Brachfogelは、2017年にシニアデベロッパーとして4Dに入社しました(4D Serverとネットワークを担当)。Apple Siliconのリリースを管理するプロダクトオーナーとして、ユーザーストーリーを書いて機能仕様に落とし込み、機能実装が顧客のニーズを満たしているかを確認する役割を担っています。Institut Supérieur d'Informatique Appliquée (INSIA) を卒業した Nicolas は、2001年にソフトウェア開発者としてのキャリアをスタートさせました。JavaとC++で数年間コーディングした後、ゲーム会社のクライアント・サーバー開発を専門に担当。サーバー開発者/アーキテクトとして、多くのゲーム(Dofus Arena、Drakerz、Trivial Pursuit Go!)のサーバーアーキテクチャに携わり、成功を収めてきました。