- See also
-
WebCFaceのメインとなるクラスです。
接続
Client オブジェクトを作るとサーバーへの接続を開始します。
1.2 1.1 Client オブジェクトを作り、start() を呼ぶことでサーバーへの接続を開始します。
バックグラウンド(別スレッド)で接続が完了するまでの間はデータの受信などはできません。
デフォルトでは127.0.0.1
(そのpc自身)の7530ポートに接続を試みますが、サーバーのポートを変更していたり別のpcに接続する場合はサーバーのアドレスとポートを指定できます。
コンストラクタに指定するのはこのクライアントの名前(Memberの名前)です。 同時に接続している他のクライアントと名前が被らないようにしてください。同じ名前で複数のクライアントが接続した場合正常に通信できない場合があります。 (おそらく後に接続したクライアントが優先される?)
- Note
- コンストラクタに名前を指定しない、または空文字列の場合、読み取り専用モードになります。
この場合データを送信することができなくなりますが、名前が被っても正常に通信できるため、同じプログラムを複数起動することができます (WebUIではこの仕様を使っています)
C++ C++のソースコードでは<webcface/webcface.h>
をincludeするとwebcfaceのすべての機能が使用できます。
1.10 <webcface/client.h>
, <webcface/value.h>
など必要なヘッダファイルだけincludeして使うこともでき、コンパイル時間を短縮できます。
wcli.start();
サーバーに接続するクライアント。
Definition client.h:18
- Clientオブジェクトのライフタイムはstaticでもローカルでも問題ありません。 初期化のタイミングにも制限はありません(main()の中でもグローバルな初期化でもok)
Client::start()
の代わりに Client::waitConnection()
を使うと 接続が完了するまで待機することができます。
- 2.0
Client::start()
の代わりに Client::waitConnection()
を使うと接続が完了してEntry(=他のクライアントが送信しているデータのリスト)をすべて受信するまで待機することができます。
- waitConnectionは通信完了までの間loopSync()を呼び出します。 詳細は後述の送受信の説明を参照
- 接続できているかどうかは
Client::connected()
で取得できます。
- 通信が切断された場合は自動で再接続します。
- 1.11.1
Client::autoReconnect(false)
をすると自動で再接続しなくなります。 その場合Client::waitConnection()
は1度だけ接続を試行し失敗してもreturnするという挙動になります。
- Note
- 1.11 接続先のアドレスが
127.0.0.1
の場合はTCPポートと別にUnixドメインソケットへの接続も試行し、 接続できた場合はUnixドメインソケットの接続を優先して使用します。
- WSL1上のクライアントは
/mnt/c/ProgramData/webcface/ポート番号.sock
への接続も試行します。これによりWSL1とWindowsの間ではどちらでサーバーを建ててもどちらのクライアントからも相互に接続できます。
- 1.11 WSL2ではUnixドメインソケットを使った相互接続はできませんが、WSL2のクライアントは接続先のアドレスが
127.0.0.1
の場合に限りホストのWindowsのIPアドレスのTCPポートへも接続を試行します。これによりWSL2とWindowsの間でも相互に通信が可能です。
Clientはstart()時に2つのスレッド(std::thread)を建てます。1つはWebSocketの送受信処理用で、送信用キューにあるメッセージを送信し、受信したら受信用キューに入れます。もう1つは受信したメッセージをパースしてコールバックを呼んだりといった処理をします。
Callメッセージ(Func呼び出しのメッセージ)を受信したときと、自分自身のFuncに対してrunAsync()を呼び出したときは、その呼び出し1回ごとに新しいスレッドを建てその中で関数を実行します。
- 2.0 Clientはstart()時に1つのスレッド(std::thread)を建てます。
- 送信用キューにデータが追加されたらそれを送信し、データを受信したら受信用キューに入れます。 また通信が切断されたときに再接続を行います。
- 受信したデータを処理してコールバックを呼ぶのは別スレッドではありません。 (詳細はこのページの送受信の章を参照)
C
wcfClient * wcfInitDefault(const char *name)
クライアントを初期化する (アドレスとポートはデフォルト)
Definition client.cc:17
wcfStatus wcfStart(wcfClient *wcli)
サーバーへの接続を別スレッドで開始する。
Definition client.cc:48
void wcfClient
Definition def_types.h:14
でclientを生成し、接続します。
1.7 引数にNULLを渡した場合空文字列と同様になります
サーバーのアドレスとポートを指定したい場合wcfInit()
を使います
wcfClient * wcfInit(const char *name, const char *host, int port)
クライアントを初期化する
Definition client.cc:7
- Note
- 1.11 接続先のアドレスが
127.0.0.1
の場合(wcfInitDefaultを使用した場合も含む)はTCPポートと別にUnixドメインソケットへの接続も試行し、 接続できた場合はUnixドメインソケットの接続を優先して使用します。
- WSL1上のクライアントは /mnt/c/ProgramData/webcface/ポート番号.sock への接続も試行します。これによりWSL1とWindowsの間ではどちらでサーバーを建ててもどちらのクライアントからも相互に接続できます。
- 1.11 WSL2ではUnixドメインソケットを使った相互接続はできませんが、WSL2のクライアントは接続先のアドレスが
127.0.0.1
の場合に限りホストのWindowsのIPアドレスのTCPポートへも接続を試行します。これによりWSL2とWindowsの間でも相互に通信が可能です。
ClientはwcfStart()時に2つのスレッド(std::thread)を建てます。1つはWebSocketの送受信処理用で、送信用キューにあるメッセージを送信し、受信したら受信用キューに入れます。もう1つは受信したメッセージをパースしてコールバックを呼んだりといった処理をします。
Callメッセージ(Func呼び出しのメッセージ)を受信したときと、自分自身のFuncに対してwcfFuncRunAsync()を呼び出したときは、その呼び出し1回ごとに新しいスレッドを建てその中で関数を実行します。
- 2.0 Clientはstart()時に1つのスレッド(std::thread)を建てます。
- 送信用キューにデータが追加されたらそれを送信し、データを受信したら受信用キューに入れます。 また通信が切断されたときに再接続を行います。
- 受信したデータを処理してコールバックを呼ぶのは別スレッドではありません。 (詳細はこのページの送受信の章を参照)
JavaScript
- ESMの例
import { Client } from "webcface";
const wcli = Client("sample");
// アドレスを指定する場合
// const wcli = Client("sample", "192.168.1.1", 7530);
wcli.start();
- 1.7 htmlからCDNを利用する例
<scripts>
const wcli = webcface.Client("sample");
// アドレスを指定する場合
// const wcli = Client("sample", "192.168.1.1", 7530);
wcli.start();
</scripts>
- Note
- 以降このドキュメントではESMのコード例のみを載せています。 CDNのWebCFaceを使う場合は上の例と同様に
webcface.クラス名
と読み替えてください。
- 接続できているかどうかは
wcli.connected
で取得できます。
- 通信が切断された場合は自動で再接続します。
- Warning
- webブラウザ上でJavaScriptから接続しようとする場合、サーバー側からみたlocalhostではなくブラウザ側からみたlocalhostへ接続しようとするので注意してください (location.host などを接続先アドレスに指定する必要があります)
Python
from webcface import Client
wcli.start()
start()
の代わりに wait_connection()
を使うと 接続が完了するまで待機することができます。
- 2.0
start()
の代わりに wait_connection()
を使うと接続が完了してEntry(=他のクライアントが送信しているデータのリスト)をすべて受信するまで待機することができます。
- waitConnectionは通信完了までの間sync()を呼び出します。 詳細は後述の送受信の説明を参照
- 接続できているかどうかは
wcli.connected
で取得できます。
- 通信が切断された場合は自動で再接続します。
- 2.0 Clientの引数に
auto_reconnect=False
を指定すると自動で再接続しなくなります。 その場合wait_connection()
は1度だけ接続を試行し失敗してもreturnするという挙動になります。
- Note
- Clientはstart()時に1つのスレッドを建てます。
- 送信用キューにデータが追加されたらそれを送信し、データを受信したら受信用キューに入れます。 また通信が切断されたときに再接続を行います。
- 2.0 受信したデータを処理してコールバックを呼ぶのは別スレッドではありません。 (詳細はこのページの送受信の章を参照)
クライアントが正常に接続できると、サーバーのログに
[info] Successfully connected and initialized.
などと表示されます。 (クライアントの名前を指定しなかった場合は表示されません)
プログラムを起動できたら、WebUIを開いてみましょう。 そして右上のメニューを開き、Clientの初期化時に指定した名前がそこに表示されていれば正しく通信できています。
Encoding
2.0
webcfaceのAPIではほぼすべての関数でマルチバイト文字列(std::string
, char *
)の代わりにワイド文字列(std::wstring
, wchar_t *
)が使用可能です。
マルチバイト文字列はデフォルトではWindows,Linux,MacOSともにUTF-8エンコーディングとして扱われます。 ただしWindowsでのみClientの初期化前に最初に webcface::usingUTF8(false)
(Cでは wcfUsingUTF8(0)
) をすることでANSIエンコーディング(日本語環境ではShiftJIS)として扱われるようにすることもできます。 (その場合webcface内部でUTF-8との変換が行われます) デフォルトでは webcface::usingUTF8(true)
(Cでは wcfUsingUTF8(1)
) が設定されています。
ワイド文字列はWindowsではUTF-16、Linux/MacOSではUTF-32でエンコードされていることを想定しています。 usingUTF8 の設定はワイド文字列の扱いには影響しませんが、 windowsで Client::loggerWStreamBuf(), loggerWOStream() を使用する場合は出力するコンソールのコードページに合わせてください。 (内部でstringに変換してコンソールへ出力されるため)
C++で文字列を返すAPI、およびCのAPI全般ではワイド文字列を使用する関数やstruct名には末尾にW
が付きます。
送受信
C++
- Client::sync() をすることでこれ以降の章で扱う各種データを送受信します。
sync()自体は送信処理はせずキューに入れるだけであり、ノンブロッキングです。
- 2.0 低レイヤーの送受信自体は別スレッドで行われますが、送信データをキューに入れる/受信したデータをキューから取り出して処理するのがsync()関数です。
- データを1回送信して終了するプログラムではなく、変化するデータを繰り返し送信/受信するようなプログラムの場合は、周期実行している場所があればそこで繰り返し呼ぶようにするとよいと思います。
while(true){
wcli.sync();
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
- 2.0 Client::loopSyncFor(), Client::loopSyncUntil() は指定した時間の間、 また Client::loopSync() は通信を切断するまで受信データの待機を続けます。 上の例のようにsync()とsleepをするならこちらを使ったほうが受信データの処理にラグが生じないのでおすすめです。
- 具体的には内部で100μsおきにsync()を呼んだり接続状態を確認しています。
- ただしサーバーに接続しておらず autoReconnect() がオフの場合は、即座にreturnします。(デッドロック回避)
while(true){
wcli.loopSyncFor(std::chrono::milliseconds(100));
}
- Note
データを受信するだけの場合もサーバーにデータのリクエストをするためsync()が必要になります。
- 1.2
Funcの呼び出しとデータ受信リクエストの送信は sync() とは非同期に行われるので sync() は不要です。
- 2.0 受信した各種データの処理がsync()で行われるため、データを受信するだけの使い方の場合でもsync()は必要です。
- Warning
- 2.0 これ以降の章で扱う各種データの受信時にコールバックを設定できますが、それはsync()を呼んだスレッドで実行されます。 そのため長時間かかるコールバックを登録した場合、その間sync()を呼んだメインスレッドがブロックされるだけでなく、他のデータの受信もできなくなるため注意してください。
-
- 1msに1回程度の頻度までは動作確認していますが、 それ以上短い周期で sync() を呼ぶとサーバーの処理が間に合わなくなるかもしれません(未検証)
C
wcfStatus wcfSync(wcfClient *wcli)
送信用にセットしたデータをすべて送信キューに入れ、受信したデータを処理する
Definition client.cc:72
- wcfSync() をすることでこれ以降の章で扱う各種データを送信します。
wcfSync()自体は送信処理はせずキューに入れるだけであり、ノンブロッキングです。
- 2.0 低レイヤーの送受信自体は別スレッドで行われますが、送信データをキューに入れる/受信したデータをキューから取り出して処理するのがwcfSync()関数です。
- データを1回送信して終了するプログラムではなく、変化するデータを繰り返し送信/受信するようなプログラムの場合は、周期実行している場所があればそこで繰り返し呼ぶようにするとよいと思います。
while(1){
usleep(100000);
}
- 2.0 wcfLoopSyncFor(wcli, timeout), wcfLoopSyncUntil(wcli, timeout) または wcfLoopSync() は指定した時間の間(または永遠に) 受信データの待機を続けます。 上の例のようにwcfSync()とsleepをするならこちらを使ったほうが受信データの処理にラグが生じないのでおすすめです。
- 具体的には内部で100μsおきにwcfSync()を呼んだり接続状態を確認しています。
- ただしサーバーに接続しておらず wcfAutoReconnect() がオフの場合は、即座にreturnします。(デッドロック回避)
while(1){
}
wcfStatus wcfLoopSyncFor(wcfClient *wcli, int timeout)
送信用にセットしたデータをすべて送信キューに入れ、受信したデータを処理する
Definition client.cc:80
- Note
Funcの呼び出しとデータ受信リクエストの送信は wcfSync() とは非同期に行われるので wcfSync() は不要です。
- 2.0 受信した各種データの処理がwcfSync()で行われるため、データを受信するだけの使い方の場合でもwcfSync()は必要です。
- Warning
- 2.0 これ以降の章で扱う各種データの受信時にコールバックを設定できますが、それはwcfSync()を呼んだスレッドで実行されます。 そのため長時間かかるコールバックを登録した場合、その間wcfSync()を呼んだメインスレッドがブロックされるだけでなく、他のデータの受信もできなくなるため注意してください。
-
- 1msに1回程度の頻度までは動作確認していますが、 それ以上短い周期で wcfSync() を呼ぶとサーバーの処理が間に合わなくなるかもしれません(未検証)
JavaScript
- sync() をすることでこれ以降の章で扱う各種データを送信します。
- メインプログラムの周期実行される場所などで繰り返し呼ぶようにしてください。
- データを1回送信して終了するプログラムではなく、変化するデータを繰り返し送信するようなプログラムの場合は、setIntervalなどを使って繰り返し呼ぶようにするとよいと思います。
setInterval(() => {
wcli.sync();
}, 100);
- データの受信処理は非同期で(sync()を呼ぶタイミングとは無関係に)行われます。
- Note
データを受信するだけの場合もサーバーにデータのリクエストをするためsync()が必要になります。
- 1.1 Funcの呼び出しとデータ受信リクエストの送信は sync() とは非同期に行われるので sync() は不要です。
Python
- sync() をすることでこれ以降の章で扱う各種データを送受信します。
データの受信処理は非同期で(sync()を呼ぶタイミングとは無関係に)行われます。
- 2.0 受信したデータをキューから取り出して処理するのもsync()関数の中で行われます。
- データを1回送信して終了するプログラムではなく、変化するデータを繰り返し送信/受信するようなプログラムの場合は、周期実行している場所があればそこで繰り返し呼ぶようにするとよいと思います。
while True:
wcli.sync()
time.sleep(0.1)
- 2.0 sync() の引数にtimeout(秒)を指定すると、指定した時間の間受信データの待機を続けます。 上の例のようにsync()とsleepをするならこちらを使ったほうが受信データの処理にラグが生じないのでおすすめです。
- デフォルトは0です(一度sync処理をした後すぐにreturnします)
- Noneを指定すると通信を切断するまでずっとsyncし、returnしません。
- ただしサーバーに接続しておらず auto_reconnect がオフの場合は、即座にreturnします。(デッドロック回避)
while True:
wcli.sync(timeout=0.1)
- 2.1 Client() のコンストラクタの引数に
auto_sync=秒数
を指定すると、 別スレッドで自動的に指定した秒数ごとに sync() が呼ばれ、データの送受信を自動で行うようになります。
- Warning
- 2.0 受信した各種データの処理がsync()で行われるため、データを受信するだけの使い方の場合でもsync()が必要になります。
- 2.0 これ以降の章で扱う各種データの受信時にコールバックを設定できますが、それはsync()を呼んだスレッドで実行されます。 そのため長時間かかるコールバックを登録した場合、その間sync()を呼んだメインスレッドがブロックされるだけでなく、他のデータの受信もできなくなるため注意してください。
切断する
C++
- Clientのデストラクタでも自動的に Client::close() が呼ばれます。
- 2.0 Client::loopSync() はclose()で停止します。 (別スレッドからでも、loopSync内から呼ばれたコールバックの中などでも可)
- Note
- 2.0 close()を呼んだ時点でサーバーに接続できていた場合は、sync()でキューに入れたメッセージがすべて送信したあとに切断されます。
- waitConnection() → sync() → close() とすれば確実にデータを送信することができます。
- start()を使ってまだ接続が完了していない場合、または1回接続した後で通信が切断された場合など、サーバーに未接続の状態でclose()が呼ばれたときはメッセージを送信することなく終了してしまいます。
- Clientのデストラクタは通信を切断するまで待機します。
C
wcfStatus wcfClose(wcfClient *wcli)
クライアントを閉じる
Definition client.cc:38
- 2.0 wcfLoopSync() はwcfClose()で停止します。 (別スレッドからでも、loopSync内から呼ばれたコールバックの中などでも可)
- Note
- 2.0 wcfClose()を呼んだ時点でサーバーに接続できていた場合は、wcfSync()でキューに入れたメッセージがすべて送信したあとに切断されます。
- wcfClose()は通信を切断するまで待機します。
- JavaScript
Python
- 1.1.1 Pythonがexitするときは確実にclose()が呼ばれます。
- 2.0 sync() はclose()で停止します。 (別スレッドからでも、sync内から呼ばれたコールバックの中などでも可)
- Note
- 1.1.1 close()を呼んだ時点(またはexitするとき)でサーバーに接続できていた場合は、sync()でキューに入れたメッセージがすべて送信したあとに切断されます。
- wait_cpnnection() → sync() → close() とすれば確実にデータを送信することができます。
- start()を使ってまだ接続が完了していない場合、または1回接続した後で通信が切断された場合など、サーバーに未接続の状態でclose()が呼ばれたときはメッセージを送信することなく終了してしまいます。
切断するとサーバーのログに
などと表示されます。
- Warning
- closeしたあと再度start()を呼んで再接続することはできません。
バージョン情報
いま使用しているWebCFaceライブラリのバージョンを確認できます。
C++ ライブラリのヘッダーファイルのバージョンは
WEBCFACE_VERSION
で文字列として(例: "1.2.0-ubuntu22.04"
)、
WEBCFACE_VERSION_MAJOR
, WEBCFACE_VERSION_MINOR
, WEBCFACE_VERSION_REVISION
で数値として(例: それぞれ 1
, 2
, 0
)
取得できます。 コンパイル時に(#if
や if constexpr
で)バージョンによって処理を変えることができます。
1.2 実行時にリンクしているライブラリのバージョンは
webcface::version_s で文字列として(例: "1.2.0-ubuntu22.04"
)、
webcface::version で数値として(例: {1, 2, 0}
)
取得できます。
- C ライブラリのヘッダーファイルのバージョンは
WEBCFACE_VERSION
で文字列として(例: "1.2.0-ubuntu22.04"
)、
WEBCFACE_VERSION_MAJOR
, WEBCFACE_VERSION_MINOR
, WEBCFACE_VERSION_REVISION
で数値として(例: それぞれ 1
, 2
, 0
)
取得できます。 コンパイル時に( #if
で)バージョンによって処理を変えることができます。
- Python
- Since
- 1.0.2
webcface.__version__
で文字列として(例: "1.0.2"
)取得できます。
サーバーの情報
serverVersion, serverName
- serverVersion でサーバーのバージョンを取得できます。
- serverName は現在は
"webcface"
という文字列しか返しません。 (今後webcface-serverを別言語で実装したりこれと同等の機能をもった別のプログラムを作ることがあったら判別できるようにするためのものです そんなことあるのか?)
- C++
wcli.serverVersion()
, wcli.serverName()
で取得できます。
- C
- Since
- 2.0
wcfServerVersion(wcli)
, wcfServerName(wcli)
で取得できます。
- JavaScript
wcli.serverVersion
, wcli.serverName
で取得できます。
- Python
wcli.server_version
, wcli.server_name
で取得できます。
serverHostName
サーバーを起動しているPCのホスト名を取得できます。 WebUI ver1.7 以降ではWebUIのページタイトルにも表示されています。
- C++
- Since
- 2.0
wcli.serverHostName()
で取得できます。
- C
- Since
- 2.0
wcfServerHostName(wcli)
で取得できます。
- JavaScript
- Since
- 1.7
wcli.serverHostName
で取得できます。
- Python
- Since
- 2.0
wcli.server_hostname
で取得できます。
- Warning
- Clientの接続が完了し受信するまでは取得できません(空文字列になります)。 受信するのは waitConnection() の待機完了よりも後です。
ログ出力
- Since
- 1.1.7 1.1
WEBCFACE_VERBOSE
環境変数が存在する場合、WebCFaceの通信に関するログ(接続、切断、メッセージのエラー)が出力されます。 また WEBCFACE_TRACE
環境変数が存在すると内部で使用しているlibcurlの出力も表示します。
1.1 ではClientのコンストラクタでlogLevelに "trace"
または "verbose"
を指定することでも表示できます。