sgcWebSockets を 5 分で

ライブラリのインストールが完了し、パレットが表示されている状態です。このページでは、そこから接続を受け付けるサーバーと、メッセージを送信して応答を読み取るクライアントまでを順に進めます。以下のコードはすべてダウンロードに同梱されているデモから抜粋したものなので、入力する代わりにプロジェクトを開くこともできます。

Delphi 7 から RAD Studio 13 まで
Windows、Linux、macOS、iOS、Android
クライアントは Standard から、サーバーは Professional から

最初のサンプルに必要なもの

非ビジュアルコンポーネント 2 つ、uses 句のユニット 1 つ、そしてイベントハンドラーのパラメーター型のための追加ユニット 1 つです。

クライアントコンポーネント

TsgcWebSocketClient は sgcWebSocket.pas で宣言され、SGC WebSockets パレットページに登録されています。Host と Port を設定してから Active を設定します。

サーバーコンポーネント

TsgcWebSocketServer は同じユニット、同じパレットページにあります。Port を設定してから Active を設定します。待ち受けを行い、ハンドシェイクをアップグレードして OnConnect を発生させます。

2 つ目のユニット

すべてのイベントは TsgcWSConnection を渡します。これは sgcWebSocket_Classes.pas にあります。デモは uses sgcWebSocket, sgcWebSocket_Classes; と記述しており、同じように記述してください。

プラットフォーム

どちらのユニットにもプラットフォームガードはなく、両コンポーネントとも ComponentPlatforms(0) で登録されているため、VCL、FMX、コンソール、サービスのいずれのターゲットでもコンパイルできます。FireMonkey クライアントのデモも同梱されています。

要件とエディション

エディションの列は、実際にコードを制御する define と、それが Source/sgcVer.inc の何行目にあるかを示しています。

項目 内容
IDE Delphi 7 から RAD Studio 13、および C++Builder 2007 から 13。Packages\ 配下に IDE バージョンごとのパッケージグループがあります。
uses 句 コンポーネントには sgcWebSocket、TsgcWSConnection には sgcWebSocket_Classes を使用します。
クライアントのエディション TsgcWebSocketClient は {$IFDEF SGC_WS_CLIENT} で囲まれています。SGC_WS_CLIENT は 697 行目、675 行目から 724 行目までの {$IFDEF SGC_EDT_STD} ブロック内で定義されています。つまり Standard 以上です。
サーバーのエディション TsgcWebSocketServer は直接 {$IFDEF SGC_EDT_PRO} で囲まれており、sgcWebSocket_Reg.pas でのパレット登録も同じガード内にあります。Professional の機能ブロックは 727 行目から 758 行目までです。つまり Professional 以上です。Standard ライセンスで使えるのはクライアントのみで、サーバーは使えません。
パレットページ 852 行目で定義されている {$IFDEF SGC_PACK_WEBSOCKETS} の下で登録されています。
プラットフォーム sgcWebSocket.pas、sgcWebSocket_Client.pas、sgcWebSocket_Server.pas にはユニットスコープのプラットフォームガードがありません。Windows では Windows ユニットが条件付きで取り込まれるだけです。

お使いのエディションが分からない場合は、Source/sgcVer.inc を開いて最初の 5 行を確認してください。そこにある SGC_EDT_* の define は累積式で、All-Access はすべてを定義し、Standard は最初の 2 つだけを定義します。

インストールとパレットの確認

zip からコンポーネントを配置できるまでの 5 つの手順です。デザイン時パッケージは実行時パッケージを参照するため、先に実行時パッケージをコンパイルしてください。

1. 展開

ダウンロードしたファイルを任意のフォルダーに展開します。このページ以降では、そのフォルダーを {$DIR} と呼びます。Source\、Packages\、Demos\、lib*\ の各フォルダーはすべてその下にあります。

2. ライブラリパス

ツール、オプション、ライブラリの順に開きます。{$DIR}\source と、お使いの IDE に対応するフォルダーを追加します。たとえば RAD Studio 13 では {$DIR}\libD13\$(Platform)、12 では {$DIR}\libD12\$(Platform) です。

3. パッケージのビルド

お使いの IDE バージョンに合わせて {$DIR}\Packages\sgcWebSocketsD13.groupproj を開きます。最初に sgcWebSocketsD13.dpk をコンパイルし、次に dclsgcWebSocketsD13.dpk をインストールします。C++Builder では同じフォルダーにある .cbproj ファイルを使用します。

4. パレットの確認

SGC WebSockets という新しいページが表示されます。Standard ビルドには TsgcWebSocketClient が含まれます。Professional 以上では、TsgcWebSocketServer、TsgcWebSocketHTTPServer、TsgcWebSocketProxyServer、TsgcWebSocketLoadBalancerServer も含まれます。

5. デモを開く

何かを書き始める前に、{$DIR}\Demos\01.WebSocket_Quick_Start\01.Server_and_Client_Chat を開いてください。ライブラリで最小の動作するペアであり、以下のコードはここから抜粋したものです。

約 20 行のサーバーとクライアント

サーバーを起動し、クライアントを起動して、文字列を送信します。サーバーのタブはポートで待ち受け、クライアントのタブは接続してメッセージを 1 件書き込みます。

uServerChat.pas
uses
  Classes, SysUtils,
  // sgc
  sgcWebSocket, sgcWebSocket_Classes;

procedure TfrmServerChat.btnStartClick(Sender: TObject);
begin
  WSServer.Port := 5418;
  WSServer.Active := True;
  memoLog.Lines.Add('#started');
end;

procedure TfrmServerChat.WSServerConnect(Connection: TsgcWSConnection);
begin
  memoLog.Lines.Add('Connected: ' + Connection.IP);
end;

procedure TfrmServerChat.WSServerDisconnect(Connection: TsgcWSConnection;
  Code: Integer);
begin
  memoLog.Lines.Add('Disconnected (' + IntToStr(Code) + '): ' + Connection.IP);
end;

procedure TfrmServerChat.WSServerMessage(Connection: TsgcWSConnection;
  const Text: string);
begin
  memoLog.Lines.Add(Text);
  // send it straight back, so the client has something to read
  Connection.WriteData('echo: ' + Text);
end;

TsgcWebSocketServer をフォームに配置して WSServer という名前を付け、オブジェクトインスペクターから 4 つのハンドラーを IDE に生成させます。Connection.IP と Connection.WriteData はどちらも TsgcWSConnection のメンバーなので、uses 句に sgcWebSocket_Classes が含まれています。

uClientChat.pas
uses
  Classes, SysUtils,
  // sgc
  sgcWebSocket, sgcWebSocket_Classes;

procedure TfrmClientChat.btnStartClick(Sender: TObject);
begin
  WSClient.Host := 'localhost';
  WSClient.Port := 5418;
  WSClient.TLS := False;
  WSClient.Active := True;
end;

procedure TfrmClientChat.btnSendClick(Sender: TObject);
begin
  if WSClient.Active then
    WSClient.WriteData('Hello from Delphi')
  else
    raise Exception.Create('Not connected');
end;

procedure TfrmClientChat.WSClientConnect(Connection: TsgcWSConnection);
begin
  memoLog.Lines.Add('#connected');
end;

procedure TfrmClientChat.WSClientMessage(Connection: TsgcWSConnection;
  const Text: string);
begin
  memoLog.Lines.Add(Text);
end;

先にサーバープロジェクトを実行し、次にこのプロジェクトを実行します。クライアントのログに #connected が表示され、echo: Hello from Delphi が OnMessage で返ってきます。この往復がクイックスタートのすべてです。

uConsole.pas
program WSConsoleClient;

{$APPTYPE CONSOLE}

uses
  Classes, SysUtils,
  // sgc
  sgcWebSocket, sgcWebSocket_Classes;

type
  TChatHandler = class
    procedure DoConnect(Connection: TsgcWSConnection);
    procedure DoMessage(Connection: TsgcWSConnection; const Text: string);
  end;

procedure TChatHandler.DoConnect(Connection: TsgcWSConnection);
begin
  Writeln('#connected');
end;

procedure TChatHandler.DoMessage(Connection: TsgcWSConnection;
  const Text: string);
begin
  Writeln('Server says: ', Text);
end;

var
  oClient: TsgcWebSocketClient;
  oHandler: TChatHandler;
begin
  oHandler := TChatHandler.Create;
  oClient := TsgcWebSocketClient.Create(nil);
  try
    oClient.Host := 'localhost';
    oClient.Port := 5418;
    oClient.WatchDog.Enabled := True;   // reconnect on its own

    // assign the handlers BEFORE Active, or the first
    // OnConnect can fire with nothing attached
    oClient.OnConnect := oHandler.DoConnect;
    oClient.OnMessage := oHandler.DoMessage;

    oClient.Active := True;
    oClient.WriteData('Hello from Delphi');
    Readln;
  finally
    oClient.Free;
    oHandler.Free;
  end;
end.

クライアントは独自のスレッドで動作するため、コンソールプログラムではメインスレッドを維持し続ける必要があります。そのために Readln を使っています。

サーバーとクライアントのタブは、同梱のデモ Demos\01.WebSocket_Quick_Start\01.Server_and_Client_Chat から、デモ固有のチェックボックスや入力ボックスの処理を取り除いたものです。3 つ目のタブは、フォームに配置する代わりに実行時に作成したコンポーネントに対して、同じ呼び出しを記述したものです。

往復通信の確認

最初の実行については 4 つのイベントで全体が分かります。先に進む前に、4 つすべてを接続しておきましょう。

Active

サーバーでは、Active := True は成功するか例外を発生させます。ポートが使用中であれば、数手順先ではなくここで分かります。

OnConnect

procedure(Connection: TsgcWSConnection)。両側で発生します。サーバーでは Connection.IP で接続してきた相手が分かり、クライアントではハンドシェイクがアップグレードされた証拠になります。

OnMessage

procedure(Connection: TsgcWSConnection; const Text: string)。クライアントにエコーが返ってくれば、往復通信がエンドツーエンドで確認できたことになります。

OnError と OnException

procedure(Connection: TsgcWSConnection; const Error: string) と procedure(Connection: TsgcWSConnection; E: Exception)。両方とも接続してください。これらがないと、障害が通知されず、何も起きていないように見えます。

初回によくあるつまずき

初回実行時の問題のほとんどは、次の 6 つのいずれかです。

TsgcWebSocketServer がパレットにない

サーバークラスは SGC_EDT_PRO が定義されている場合のみ、sgcWebSocket.pas の 130 行目でコンパイルされ、同じガード内でのみ登録されます。Standard ビルドではクライアントはありますが、サーバーはありません。これはライセンスによるもので、インストールの不具合ではありません。

未宣言の識別子 TsgcWSConnection

コンポーネントは sgcWebSocket に、接続オブジェクトは sgcWebSocket_Classes にあります。2 つ目のユニットを uses 句に追加してください。同梱のデモにはすべて両方が含まれています。

クライアントが接続した後に切断される

WatchDog.Enabled := True を設定して、切断された接続が自動的に再接続されるようにし、OnError と OnException を処理してください。ハンドラーがない状態での無通知の切断は、何も起きていないように見えます。

サーバーに何も届かない

書き込む前に、クライアントが実際に接続されていることを確認してください。非アクティブなクライアントに対する WriteData は何の効果もありません。デモが送信前に if WSClient.Active then を確認しているのはそのためです。

ポートがすでに使用されている

サーバーの別のインスタンスや別のプログラムが、まだそのポートを使用しています。それを停止するか、サーバーを空いているポートに変更してください。デモの既定値は 5416 と 5418 です。

Linux やモバイルで TLS が失敗する

wss:// 接続には、動作する TLS バックエンドが必要です。TLSOptions.IOHandler で選択します。OpenSSL はどこでも使え、SChannel は Windows で DLL の配布が不要で、Apple と Android のネイティブハンドラーは Enterprise エディションで利用できます。

最初のメッセージの次に進む先

チャットのペアは出発点にすぎません。作業が向かいやすい 4 つの方向を示します。いずれも同じライブラリに含まれています。

実際のプロトコルを使う

同じクライアントで、MQTT、AMQP、STOMP、Kafka、WAMP のサブプロトコルコンポーネントを利用できます。いずれかを配置し、その Client プロパティを TsgcWebSocketClient に向ければ、ブローカーに接続できます。

sgcMQ クイックスタートとプロトコルの概要

WebSocket に加えて HTTP も提供する

TsgcWebSocketHTTPServer は、通常の HTTP リクエストと WebSocket のアップグレードを同じポートで処理します。ブラウザーがソケットを開く前にページを取得する必要がある場合に適しています。

HTTP コンポーネント

1 つのプロセスを超えてスケールする

Enterprise エディションでは、クラスタリング、ロードバランサーサーバー、プロキシサーバーが追加され、1 つの論理エンドポイントを複数のサーバープロセスの前段に置けます。

クラスターのリファレンスとロードバランサーのリファレンス

出荷前に堅牢化する

レート制限、サーキットブレーカー、API キーマネージャー、ファイアウォールの各コンポーネントは、既存のサーバーにそのまま追加できます。

レートリミッター、サーキットブレーカー、ファイアウォール

リファレンス、デモ、ドキュメント

リファレンスページには、すべてのプロパティとイベントが記載されています。デモプロジェクトはダウンロードに含まれており、Demos\01.WebSocket_Quick_Start の下にあります。

リファレンス、WebSocket クライアント TsgcWebSocketClient のすべてのプロパティ、メソッド、イベント。
リファレンス、WebSocket サーバー TsgcWebSocketServer のバインド、認証、ブロードキャスト、接続管理。
オンラインヘルプ、TsgcWebSocketClient 自動生成されたコンポーネントリファレンスで、常に最新リリースに対応しています。
必要なエディションは Standard、Professional、Enterprise、All-Access がそれぞれ有効にする機能を、機能ごとに説明します。
体験版のダウンロード 製品版と同じインストーラーで、期間限定、IDE バージョンごとに 1 つです。
ユーザーマニュアル (PDF) ライブラリ内のすべてのコンポーネントを網羅した完全なマニュアルです。

関連資料:WebSocket とは何か、クライアントの接続と WatchDog のイベント、WebSocket サーバーのセキュリティ。各製品にはそれぞれクイックスタートがあり、はじめにのページに一覧があります。

sgcWebSockets クイックスタートに関するよくある質問

sgcWebSocket で TsgcWebSocketClient と TsgcWebSocketServer が使えます。すべてのイベントは TsgcWSConnection を渡し、その型は sgcWebSocket_Classes で宣言されているため、こちらも追加してください。同梱のデモは uses sgcWebSocket, sgcWebSocket_Classes; と記述しており、サーバーのデモではさらに sgcWebSocket_Server を追加しています。
サーバークラスは {$IFDEF SGC_EDT_PRO} の内側でコンパイルされ、sgcWebSocket_Reg.pas でのパレット登録も同じガード内にあります。SGC_EDT_PRO は、sgcVer.inc の 727 行目から 758 行目にある Professional の機能ブロックを有効にします。Standard ビルドではクライアントのみがコンパイルされます。クライアントの define である SGC_WS_CLIENT は、675 行目から 724 行目の Standard ブロック内の 697 行目にあります。
これらは sgcWebSocket_Classes.pas に由来します。OnConnect は procedure(Connection: TsgcWSConnection)、OnDisconnect は procedure(Connection: TsgcWSConnection; Code: Integer)、OnMessage は procedure(Connection: TsgcWSConnection; const Text: string)、OnError は procedure(Connection: TsgcWSConnection; const Error: string)、OnException は procedure(Connection: TsgcWSConnection; E: Exception) です。パラメーターの過不足は最初のプロジェクトで最もよくあるコンパイルエラーなので、手入力せずに IDE に生成させてください。
はい。sgcWebSocket.pas、sgcWebSocket_Client.pas、sgcWebSocket_Server.pas にはユニットスコープのプラットフォームガードがなく、両コンポーネントとも ComponentPlatforms(0) で登録されているため、IDE がターゲットを制限することはありません。FireMonkey のクライアントとサーバーのデモは Demos\01.WebSocket_Quick_Start\07.Firemonkey_Server_and_Client に同梱されています。ライブラリ内でプラットフォームが制限されている WebSocket コンポーネントは TsgcWebSocketClient_WinHTTP だけで、Win32 と Win64 に対応しています。
クライアントで TLS := True を設定し、Port を TLS ポートに向けます。次に TLSOptions.IOHandler で TLS バックエンドを選択します。OpenSSL はどこでも動作し、Windows では実行ファイルと同じ場所に libcrypto-3.dll と libssl-3.dll が必要です。SChannel は Windows 専用で、追加ファイルは不要です。Apple と Android のネイティブハンドラーは Enterprise の機能です。
はい。上の 3 つ目のタブがまさにそれです。Active := True を設定する前にイベントハンドラーを割り当ててください。そうしないと、ハンドラーが接続される前に最初の OnConnect が発生することがあります。コンソールアプリケーションでは、クライアントが独自のスレッドで動作するためメインスレッドを維持し続ける必要があり、サンプルが Readln で終わっているのはそのためです。
切断されたクライアントを、指定した間隔で再接続します。長時間動作するアプリケーションでは有効にしてください。ネットワークの一時的な障害でソケットが閉じられると、アプリケーションが通知なしに切断されたままになってしまいます。WatchDog.Enabled := True を設定し、既定値が積極的すぎる場合は WatchDog.Interval と WatchDog.Attempts を調整してください。
ダウンロードに含まれる Demos\ の下にあります。このページで使用しているペアは 01.WebSocket_Quick_Start\01.Server_and_Client_Chat です。早めに開いておきたいものとして、資格情報を確認するサーバーの 06.Authentication、クロスプラットフォームクライアントの 07.Firemonkey_Server_and_Client、接続のサブセットへのブロードキャストの 12.Groups もあります。
最もお得な選択: All-AccesseSeGeCe の全製品にプレミアムサポートが付いて、年間 €1,059 からご利用いただけます。
All-Access の価格を見る

構築を始める準備はできましたか?

体験版をダウンロードして、自分のコードを書く前にチャットのデモを実行してみてください。