![]() ![]() ![]()
|
SophiaFramework 2.2 |
#include <SFUNetworkStream.hpp>
class SFUNetworkStream : public SFUStream;
typedef SFUNetworkStream& SFUNetworkStreamRef; typedef SFUNetworkStream* SFUNetworkStreamPtr; typedef SFUNetworkStream** SFUNetworkStreamHandle; typedef const SFUNetworkStream ConstSFUNetworkStream; typedef const SFUNetworkStream& ConstSFUNetworkStreamRef; typedef const SFUNetworkStream* ConstSFUNetworkStreamPtr; typedef const SFUNetworkStream** ConstSFUNetworkStreamHandle;
SFUNetworkStream は、BREW API の ISocket をカプセル化し、 ハイレベルな TCP/UDP ソケット機能を提供します。
読み取りバッファと書き込みバッファ
ネットワーク ストリームでは、 送信するデータを Put や インサータ (<<) で書き込みます。 書き込まれたデータは内部の書き込みバッファに蓄積されます。 その後、相手ホストに実際にデータを送信するときに Flush を呼び出します。 書き込みバッファの初期サイズはデフォルトで 1024 byte ですが、 SetWriteBufferSize で初期サイズを変更できます。 書き込みバッファは必要となれば自動拡張していきますので、 開発者は書き込みバッファのサイズを気にする必要はありません。
また、相手ホスト (UDP の場合は任意のホスト) からデータを受信する場合は、 読み取りバッファにデータが格納されます。 これを行うには、 Fetch を呼び出します。 読み取りバッファにデータが存在する場合、 Get や エクストラクタ (>>) でデータを読み取ることができます。 読み取りバッファの初期サイズはデフォルトで 1024 byte ですが、 SetReadBufferSize で初期サイズを変更できます。 読み取りバッファのサイズまでしかデータを受信することはできません。 それ以上のデータを受信するには、 読み取りバッファのデータを読み出して空きを作ってから、再度 Fetch を呼び出してください。
TCP ソケットの場合、 読み取りバッファにデータが存在する状態で Fetch を呼び出すと、既存のデータに新たに受信したデータが追加されます。 UDP ソケットの場合は、 Fetch を呼び出してデータを受信すると、 読み取りバッファの既存のデータは失われます。
コールバック関数
BREW のネットワーク通信処理はノンブロッキング モデルを採用しており、 接続、バインド、受信、送信などの通信処理は、 コールバック関数により成功または失敗が通知されます。
以下の表では、コールバック関数に通知される通知コードについて説明しています。
表 11. コールバック関数への通知
| 通知コード | 説明 |
| SFUNetworkStream::NOTIFY_CONNECT | Open を呼び出した後で、 TCP サーバーへの接続が成功したか失敗したときに通知されます。 TCP ソケットでのみ通知されます。 |
| SFUNetworkStream::NOTIFY_BIND | Bind を呼び出した後で、 バインドが成功したか失敗したときに通知されます。 UDP ソケットでのみ通知されます。 |
| SFUNetworkStream::NOTIFY_READ | Fetch を呼び出した後で、 読み取りバッファへのデータ受信に成功したか失敗したときに通知されます。 読み取りバッファに少しでもデータを受信できれば受信成功となります。 |
| SFUNetworkStream::NOTIFY_WRITE | Flush を呼び出した後で、 書き込みバッファのデータ送信に成功したか失敗したときに通知されます。 書き込みバッファにあるデータがすべて送信完了した場合にのみ送信成功となります。 |
TCP ソケットの使用手順
SFUNetworkStream を TCP ソケットとして使用するには、 以下の手順で使用します。
UDP ソケットの使用手順
SFUNetworkStream を UDP ソケットとして使用する手順は、 TCP ソケットの場合とほとんど同じですが、 以下の点が異なります。
エラー値について
SFUNetworkStream のメンバ関数は、 エラーが発生した場合に、 エラー値を内部に記録します。 このエラー値は Exception により取得することができます。 SFUNetworkStream では主に下記のエラー値が使用されます。
表 12. SFUNetworkStream のエラー値
| エラー値 | 意味 |
| SFERR_NO_ERROR | 関数は成功しました。 |
| SFERR_FAILED | 関数は失敗しました。 |
| SFERR_NO_MEMORY | メモリ不足により失敗しました。 |
| SFERR_INVALID_PARAM | 引数が不正です。 |
| SFERR_STREAM_NOT_OPEN | ストリームがオープンされていません。 |
| SFERR_STREAM_ALREADY_OPEN | ストリームはすでにオープンされています。 |
| SFERR_STREAM_READ_FAILED | データの読み取りに失敗しました。 |
| SFERR_STREAM_WRITE_FAILED | データの書き込みに失敗しました。 |
エラーコードについて
接続、バインド、受信、送信の過程で発生したエラーは、 SFUNetworkStream のエラー値としては保持されず、 コールバック関数の引数に渡されます。 これをエラーコードと呼びます。
ネットワーク ストリームの使用例については、 項6.6 を参照してください。
| コンストラクタ/デストラクタ | ||
|---|---|---|
| public |
SFUNetworkStream | SFUNetworkStream クラスのコンストラクタです。 |
| public |
~SFUNetworkStream | SFUNetworkStream クラスのデストラクタです。 |
| パブリック関数 | ||
|---|---|---|
| public |
Available | 読み取りバッファから読み取り可能なデータサイズを取得します。 |
| public |
Bind | UDP ソケットを指定したポート番号へバインドします。 |
| public |
Close | ネットワーク ストリームをクローズします。 |
| public |
Exception (SFAException から継承) | エラーコードを取得/設定します。 |
| public |
Fetch | ネットワークから読み取りバッファにデータを受信します。 |
| public |
Flush | 書き込みバッファのデータを実際にネットワークへ送信します。 |
| public |
Get | 読み取りバッファからデータを読み取ります。 |
| public |
GetPeerName | 通信の相手ホストの IP アドレスとポート番号を取得します。 |
| public |
GetReadBufferSize | 読み取りバッファのサイズを取得します。 |
| public |
GetWriteBufferSize | 書き込みバッファのサイズを取得します。 |
| public |
IsEOS | ストリームの終端に達したか判定します。 |
| public |
IsFetchable | 読み取りバッファにデータを受信可能かどうか判定します。 |
| public |
IsFlushing | データ送信中であるか判定します。 |
| public |
Open | ストリームをオープンします。 |
| public |
Put | 書き込みバッファにデータを書き込みます。 |
| public |
Seek | ネットワーク ストリームでは、この関数は使用できません。 |
| public |
SetPeerName | UDP ソケットのデータ送信先を設定します。 |
| public |
SetReadBufferSize | 読み取りバッファのサイズを設定します。 |
| public |
SetWriteBufferSize | 書き込みバッファの初期サイズを設定します。 |
| public |
Tell | 現在までに読み取った総バイト数と、 現在までに書き込んだ総バイト数を返します。 |
| public |
operator<< (SFUStream から継承) | ストリームのインサータ (書き込み演算子) です。 |
| public |
operator>> (SFUStream から継承) | ストリームのエクストラクタ (読み取り演算子) です。 |
| プロテクト関数 | ||
|---|---|---|
| public |
Exception (SFAException から継承) | エラーコードを取得/設定します。 |
| protected |
endianbig (SFUStream から継承) | 読み込みモード/書き込みモードのエンディアンをビッグエンディアンに設定します。 |
| protected |
endianlittle (SFUStream から継承) | 読み込みモード/書き込みモードのエンディアンをリトルエンディアンに設定します。 |
| protected |
multi (SFUStream から継承) | 任意のサイズのデータを読み書きします。 |
| protected |
offset (SFUStream から継承) | ストリームの読み込み/書き込みポインタを指定された位置に移動します。 |
| protected |
seek (SFUStream から継承) | ストリームの読み込み/書き込みポインタを指定された位置に移動します。 |
| 型 | ||
|---|---|---|
| EndianEnum (SFUStream から継承) | ストリームのエンディアン変換を表す定数です。 | |
| NO_ERROR (SFAException から継承) | エラーがないことを表す定数です。 | |
| NetworkStreamSPP | コールバック関数の型です。 | |
| NotifyEnum | コールバック関数への通知コードを表す型です。 | |
| SeekEnum (SFUStream から継承) | ストリームのシークモードを表す定数です。 | |
[ public ] SFUNetworkStream(Void);
データメンバを初期化します。 エラー値 SFERR_NO_ERROR が設定されます。 この段階では、 ネットワーク通信を行うためのリソース確保は行われません。
[ public, virtual ] ~SFUNetworkStream(Void);
ソケットがオープンされている場合は、自動的にクローズします。
[ public, virtual ] UInt32 Available(Void);
オープン状態でない場合は 0 を返します。
UDP ソケットを指定したポート番号へバインドします。
この関数が成功した場合、 コールバック関数に SFUNetworkStream::NOTIFY_BIND 通知が行われます。 この関数が成功したからといって、 バインドに成功したわけではありません。 バインドに成功したかどうかは、 コールバック関数のエラーコードとして通知されます。
以下のコードでは、 バインドが成功した場合に、 相手ホストにデータを送信しています。 _net はネットワーク ストリームのインスタンスです。
Void TestUdp::OnNotify(SFUNetworkStream::NotifyEnum notify, SFCError error)
{
switch (notify) {
case SFUNetworkStream::NOTIFY_BIND: // バインド通知の場合
// バインドが成功したら
if (error == SFERR_NO_ERROR) {
_net << "GET DATA";
_net.Flush();
}
// バインドに失敗したら
else {
ShowError("ネットワーク通信ができません。");
}
break;
.....
};
}
[ public ] Void Close(Void);
内部で使用している ISocket インスタンスや INetMgr インスタンスを解放し、 書き込みバッファや読み取りバッファを解放します。 エラー値は SFERR_NO_ERROR に設定されます。
BREW アプレットのサスペンド時には、 この関数を呼び出すことで端末のリソースを解放することを推奨します。
[ public ] Void Fetch(Void);
ネットワークから読み取りバッファにデータを受信します。
この関数が失敗した場合は、コールバック関数は呼び出されません。 関数が成功すると、必ずコールバック関数が呼び出されますが、 呼び出されるタイミングは保証されません。 この関数の呼び出しは非同期であり、 データが受信されるまで待機するわけではありませんし、 すぐにコールバック関数が呼び出されるわけでもありません。
この関数が成功したからといって、 データ受信が成功するとは限りません。 データ受信が成功したかどうかは、 コールバック関数に通知されるエラーコードで知ることができます。
以下のコードでは、 データを受信したときに、 1 文字づつ読み取っています。 読み取りバッファ内のデータをすべて読み取ると、 さらなるデータを受信するために、ふたたび Fetch を呼び出しています。
Void TestSmallRead::OnNotify(SFUNetworkStream::NotifyEnum notify, SFCError error)
{
case SFUNetworkStream::NOTIFY_READ:
UInt32 availSize = _net.Available();
for ( ; availSize > 0; availSize--) {
AChar c;
_net >> c;
... c を利用したコード ...
}
// さらにデータを受信する
_net.Fetch();
break;
....
}
}
[ public ] Void Flush(Void);
書き込みバッファのデータを実際にネットワークへ送信します。
この関数が失敗した場合は、コールバック関数は呼び出されません。 関数が成功すると、必ずコールバック関数が呼び出されますが、 呼び出されるタイミングは保証されません。 この関数の呼び出しは非同期であり、 データが送信されるまで待機するわけではありませんし、 すぐにコールバック関数が呼び出されるわけでもありません。
この関数が成功したからといって、 データ送信が成功するとは限りません。 データ送信が成功したかどうかは、 コールバック関数に通知されるエラーコードで知ることができます。
以下のコードは、echo サーバーに対してデータを送信し、 送信が完了した時点で、サーバーからデータを受信するように要求しています。
Void TestEcho::OnNotify(SFUNetworkStream::NotifyEnum notify, SFCError error)
{
switch (notify) {
case SFUNetworkStream::NOTIFY_CONNECT: // 接続が成功/失敗した場合
if (error == SFERR_NO_ERROR) {
_net << "DATA";
_net.Flush();
}
else {
ShowError("サーバーへの接続に失敗");
}
break;
case SFUNetworkStream::NOTIFY_WRITE: // 送信が成功/失敗した場合
if (error == SFERR_NO_ERROR) {
_net.Fetch();
}
else {
ShowError("データ送信に失敗");
}
break;
}
case SFUNetworkStream::NOTIFY_READ: // 受信が成功/失敗した場合
if (error == SFERR_NO_ERROR) {
UInt32 avaiSize = _net.Available();
for ( ; avilaSize > 0; availSize--) {
AChar c;
_net >> c;
ShowData(c);
}
}
else {
ShowError("データ受信に失敗");
}
break;
}
}
実際に読み取ったサイズを返します。 この関数が失敗すると 0 を返します。 この関数が成功すると size を返します。
読み取りバッファからデータを読み取ります。
失敗すると、読み取りポインタはまったく進みません。 成功すると、読み取りポインタは size の分だけ進みます。
この関数は SFUStream::Get を実装したものです。 エクストラクタ (>>) は実際にはこの関数を呼び出します。
以下のコードは、読み取りバッファから文字列データを読み取っています。 エクストラクタは実際には Get 関数を呼び出します。
// _net は SFUNetworkStream のインスタンスとします。
SFUAnsiString str;
_net >> str;
if (_net.Exception() != SFERR_NO_ERROR) {
...
}
[ public ] SFUIPEndpoint GetPeerName(Void);
通信の相手ホストの IP アドレスとポート番号を取得します。
TCP ソケットの場合は、 Open で指定した IP アドレスとポート番号を返します。
UDP ソケットの場合で NOTIFY_READ コールバックの中で呼ばれた場合は、 受信したパケットを送信してきた相手ホストの IP アドレスとポート番号を返します。
下記のコードでは、UDP ソケットでパケットを受信したときに、 相手ホストの IP アドレスとポート番号とそのデータを 文字列として取得しています。 UDP ソケットでは相手ホストが毎回変化する可能性があることに注意してください。
Void TestUdp::OnNotify(SFUNetworkStream::NotifyEnum notify, SFCError error)
{
SFUIPEndpoint ip;
switch (notify) {
case SFUNetworkStream::NOTIFY_READ: // 受信が成功/失敗した場合
if (error == SFERR_NO_ERROR) {
ip = _net.GetPeerName();
ShowHostInfo(ip.ToString());
}
// 次のデータを受信
_net.Fetch();
break;
...
}
}
[ public ] UInt32 GetReadBufferSize(Void);
[ public ] UInt32 GetWriteBufferSize(Void);
[ public, virtual ] Bool IsEOS(Void);
ストリームの終端に達したか判定します。 ストリームがオープンされていない場合は TRUE が返されます。
TCP ソケットの場合、 接続先のサーバーが接続を切断し、 かつ、 読み取りバッファにデータがなくなったときにストリーム終端となります。
UDP ソケットの場合、 ストリーム終端に達することはありません。
[ public ] Bool IsFetchable(Void);
読み取りバッファにデータを受信可能かどうか判定します。 ソケットがオープンされていない場合は FALSE を返します。
TCP ソケットでは、接続先のサーバーが接続を切断すると受信不可能になります。
UDP ソケットでは受信不可能になることはありません。
受信可能な場合、 Fetch を呼び出すことで、受信できます。
[ public ] Bool IsFlushing(Void);
書き込みバッファのデータを送信中であれば TRUE を返します。
[ public ] SFCError Open( ConstSFUIPEndpointRef endpoint // 相手ホストのアドレス NetSocket type // ソケット タイプ (TCP/UDP) NetworkStreamSPP func // コールバック関数 VoidPtr data // コールバック関数に渡すデータ );
相手ホストの IP アドレスとポート番号を指定します。 TCP ソケットの場合、接続先のサーバーのアドレスになります。 UDP ソケットの場合、データ送信先のデフォルトのアドレスになります。
ソケット タイプを指定します。 TCP ソケットの場合は AEE_SOCK_STREAM を指定します。 UDP ソケットの場合は AEE_SOCK_DGRAM を指定します。
通知を受け取るコールバック関数を指定します。
コールバック関数に渡すデータを指定します。
エラー値を返します。 エラー値は Exception でも取得できます。
ストリームをオープンします。 ネットワーク通信のためのソケットを作成し、 読み取りバッファ、書き込みバッファを確保します。
TCP ソケットの場合と、UDP ソケットの場合で、 その後の挙動が異なります。
TCP ソケットの場合、 ソケットのオープンに成功した場合は接続を試みます。 接続に成功した場合は、コールバック関数により通知コード SFUNetworkStream::NOTIFY_CONNECT でエラーコード SUCCESS が通知されます。 接続に失敗した場合は、コールバック関数により通知コード SFUNetworkStream::NOTIFY_CONNECT で、エラーコードは BREW API 関数 ISOCKET_Connect() のエラーコードが通知されます。
UDP ソケットの場合、 Open を呼び出してもコールバック関数に通知されません。 UDP ソケットでは通常、Open を呼び出した後で、 Bind を呼び出してください。 endpoint 引数は送信先アドレスのデフォルト値として保持されます。 この後、送信先アドレスを変更するには SetPeerName を使用してください。
下記のコードは、 TCP サーバーへの接続を開始し、 接続が成功したらデータを送信しています。
#define SERVER_HOST "192.168.101.198" // サーバーの IP アドレス
#define SERVER_PORT 7 // サーバーのポート番号
class TestTcp {
SFUIPEndpoint _endpoint;
SFUNetworkStream _net;
// 接続を開始する関数
Void Start(Void);
// コールバック関数となる静的メンバ関数
static Void OnNotifyEntry(SFUNetworkStream::NotifyEnum notify, SFCError error, VoidPtr data);
{ ((TestTcp*)data)->OnNotify(notify, error); }
// コールバック関数を処理するメンバ関数
Void OnNotify(SFUNetworkStream::NotifyEnum notify, SFCError error);
};
/**
* TCP サーバーへの接続を開始する関数
*/
Void TestTcp::Start(Void)
{
// 書き込みバッファ サイズを設定する
_net.SetWriteBufferSize(512);
// 読み取りバッファ サイズを設定する
_net.SetReadBufferSize(1024);
// ソケットをオープン
_endpoint.Set(SERVER_HOST, HTONS(SERVER_PORT));
_net.Open(_endpoint, AEE_SOCK_STREAM, OnNotifyEntry, this);
}
/**
* ネットワーク ストリームの通知を受け取るコールバック関数
*/
Void TestTcp::OnNotify(SFUNetworkStream::NotifyEnum notify, SFCError error)
{
switch (notify) {
case SFUNetworkStream::NOTIFY_CONNECT: // 接続が成功/失敗した場合
if (error == SFERR_NO_ERR) {
_net << "DATA";
_net.Flush();
break;
}
else {
ShowError("接続に失敗");
}
....
}
}
[ public, virtual ] UInt32 Put( ConstVoidPtr ptr // 書き込みを行うデータのアドレス UInt32 size // 書き込むデータ サイズ );
実際に書き込んだサイズを返します。 この関数が失敗すると 0 を返します。 この関数が成功すると size を返します。
書き込みバッファにデータを書き込みます。
失敗すると、書き込みポインタはまったく進みません。 成功すると、書き込みポインタは size の分だけ進みます。
この関数は SFUStream::Put を実装したものです。 インサータ (<<) は、実際にはこの関数を呼び出します。
以下のコードは、書き込みバッファに文字列データを書き込んでいます。 インサータは実際には Get 関数を呼び出します。
// _net は SFUNetworkStream のインスタンスとします。
_net << "DATA";
if (_net.Exception() != SFERR_NO_ERROR) {
...
}
ネットワーク ストリームでは、この関数は使用できません。 呼び出すとエラー値 SFERR_UNAVAILABLE が設定され、 UInt32(-1) が返ります。
この関数は SFUStream::Seek を実装したものです。
[ public ] Void SetPeerName( ConstSFUIPEndpointRef peer // 相手ホストの IP アドレスとポート番号 );
UDP ソケットのデータ送信先を設定します。 データ送信中である場合は、 この関数を呼び出しても何も行われません。 データ送信先を変更する場合は、 現在データを送信中ではないことを確認した上で変更してください。
TCO ソケットに対しては何も行われません。
読み取りバッファのサイズを設定します。 設定された値は、次回の Open 呼び出し時に使用されます。 現在オープンされているストリームに対してこの関数を呼び出しても 読み取りバッファのサイズは変化しません。
Open を呼び出すことで読み取りバッファがいったん作成されると、 次回 Open を呼び出すまでは、 そのサイズが拡張されることはありません。 したがって、読み取りバッファのサイズを超えるデータを受信することはできません。
TCP ソケットにいおて読み取りバッファがいっぱいで受信できない場合、 読み取りバッファからデータを読み取ってバッファを空けた上で、 再度 Fetch を呼び出すと、受信できます。
UDP ソケットでは Fetch が成功した時点で読み取りバッファがクリアされますので、 読み取りバッファがいっぱいで受信できないということはありません。
書き込みバッファの初期サイズを設定します。 設定された値は、次回の Open 呼び出し時に使用されます。 現在オープンされているストリームに対してこの関数を呼び出しても 書き込みバッファのサイズは変化しません。
書き込みバッファは、必要となれば自動的にサイズが拡張していきますので、 ここで設定されたサイズまでしか書き込めないわけでありません。
[ public, virtual ] UInt32 Tell( ModeEnum mode // 読み取りモード/書き込みモード );
現在までに読み取った総バイト数を取得するときは、 SFUStream::MODE_READ を指定してください。 現在までに書き込んだ総バイト数を取得するときは、 SFUStream::MODE_WRITE を指定してください。
この関数は SFUStream::Tell の実装です。
typedef Void(* SFUNetworkStream::NetworkStreamSPP)(NotifyEnum notify, SFCError error, VoidPtr data)
通知コードです。
エラーコードです。
ユーザー定義データです。
ネットワーク ストリームで、 接続、バインド、受信、送信の成功/失敗を通知してもらうには、 Open にこの型のコールバック関数を登録します。
コールバック関数は通常、 クラスの静的関数を介してクラスのメンバ関数に処理を委譲するとよいでしょう。 これによりオブジェクト指向に沿ったプログラミングが可能となります。 下記のコードを参考にしてください。
class TestTcp {
SFUIPEndpoint _endpoint;
SFUNetworkStream _net;
// 接続を開始する関数
Void Start(Void);
// コールバック関数となる静的メンバ関数
static Void OnNotifyEntry(SFUNetworkStream::NotifyEnum notify, SFCError error, VoidPtr data);
{ ((TestTcp*)data)->OnNotify(notify, error); }
// コールバック関数を処理するメンバ関数
Void OnNotify(SFUNetworkStream::NotifyEnum notify, SFCError error);
};
/**
* TCP サーバーへの接続を開始する関数
*/
Void TestTcp::Start(Void)
{
....
_net.Open(_endpoint, AEE_SOCK_STREAM, OnNotifyEntry, this);
....
}
/**
* ネットワーク ストリームの通知を受け取るコールバック関数
*/
Void TestTcp::OnNotify(SFUNetworkStream::NotifyEnum notify, SFCError error)
{
....
}
[ public ]
enum NotifyEnum {
NOTIFY_CONNECT = 1,
NOTIFY_BIND,
NOTIFY_READ,
NOTIFY_WRITE
};
コールバック関数への通知コードを表す型です。 以下の意味をもちます。
| Copyright(C) 2003-2004 Sophia Cradle Inc., All Rights Reserved. |
![]() ![]() ![]()
|