前のページ次のページ上に戻るホーム SophiaFramework UNIVERSE 5.3

18.4. SFXTCPSocket クラス

SFXTCPSocket クラスは、 TCP クライアントと TCP サーバーを実装する機能を提供します。

このクラスでは、ストリームを利用したデータ送受信が可能です。

ストリームを利用しない場合は SFXTCPSocket::Write / SFXTCPSocket::Read 関数を使用してデータを送受信します。

■ SFXTCPSocket クラスの使用手順(TCP クライアントの実装)

  1. TCP ソケット(SFXTCPSocket インスタンス)を作成します。
  2. SFXTCPSocket::Open 関数を呼び出して、 TCP ソケットを開きます。
  3. 必要に応じて SFXTCPSocket::Bind 関数を呼び出して、ローカル の IP アドレスとポート番号を TCP ソケットにバインドします。 バインド処理を省略した場合は、デフォルトのポート番号がバインドされます。
  4. SFXTCPSocket::Connect 関数を呼び出して、サーバーへ接続リクエストを送信します。
  5. サーバーへの接続リクエストの結果は、SFXTCPSocket::Connect 関数で登録したコールバック関数に通知されます。
  6. SFXTCPSocket::GetStreamReader 関数を呼び出して入力ストリームを取得し、データを受信します (ストリームを利用しない場合は、SFXTCPSocket::Read 関数を使用してデータを受信します)。
  7. SFXTCPSocket::GetStreamWriter 関数を呼び出して出力ストリームを取得し、データを送信します (ストリームを利用しない場合は、SFXTCPSocket::Write 関数を使用してデータを送信します)。
  8. 6. と 7. のデータ送受信処理を繰り返します。
  9. SFXTCPSocket::Close 関数を呼び出して、TCP ソケットを閉じます。

参照: ネットワーク: TCP ソケット通信

例 18.4. ストリームを使用した TCP ソケット通信

// コールバック関数で使用するので、_socket はクラスのメンバ変数として定義する
class MyClass {
private:
    SFXTCPSocket _socket;                // SFXTCPSocket インスタンス
    SFXAnsiStringStreamReader  _reader;  // データ受信用ストリーム
    SFXAnsiStringStreamWriter  _writer;  // データ送信用ストリーム
public:
    Void Start(Void);
    XALLBACK_DECLARE_SFXTCPSOCKET(OnConnect)
    XALLBACK_DECLARE_SFXANSISTRINGSTREAMREADER(OnFetch)
    XALLBACK_DECLARE_SFXANSISTRINGSTREAMWRITER(OnFlush)
};

Void MyClass::Start(Void)
{
    SFCError error;
    SFXSocketAddress host("www.example.com:995");

    // ソケットを開く
    if ((error = _socket.Open()) == SFERR_NO_ERROR) {
 
        // サーバーに接続する
        // ※1. 接続要求の結果は、OnConnect 関数に通知される
        // ※2. ホスト名(host)は自動的に解決される
        error = _socket.Connect(host, XALLBACK_INTERNAL(OnConnect));
    }
    if (error != SFERR_NO_ERROR) { 

        // エラーが発生したとき
        _socket.Close();
    }
    return;
}

// 接続要求の結果が通知されるコールバック関数
XALLBACK_IMPLEMENT_SFXTCPSOCKET(MyClass, OnConnect, error)
{
    // 送信する文字列
    static AChar message[] = "GET / HTTP/1.0\r\n\r\n";

    if (error == SFERR_NO_ERROR) {

        // データ送信用ストリームを取得する
        // ※ size 引数を指定していないのでストリームバッファは可変長
        if ((error = _socket.GetStreamWriter(&_writer)) == SFERR_NO_ERROR) {

            // message 変数からストリームバッファにデータを書き込む
            // ※ message 変数のサイズに合わせてバッファは自動的に拡張される
            if ((error = _writer.Write(message, lengthof(message))) == SFERR_NO_ERROR) {

                // フラッシュを行う: 実際にストリームバッファからソケットにデータを送信する
                // ※1. データ送信(フラッシュ)の結果は、OnFlush 関数に通知される
                // ※2. 可変長バッファストリームの場合、1 回の Flush 関数呼び出しでデータ送信は完了する
                error = _writer.Flush(XALLBACK_INTERNAL(OnFlush));
            }
            if (error != SFERR_NO_ERROR) { 

                // エラーが発生したとき
                 _writer.Release();
            }
        }
    }
    if (error != SFERR_NO_ERROR) { 

       // エラーが発生したとき
       _socket.Close();
    }
    return;
}

// データ送信(フラッシュ)の結果が通知されるコールバック関数
XALLBACK_IMPLEMENT_SFXANSISTRINGSTREAMWRITER(MyClass, OnFlush, error)
{
    // 送信が終わったのでデータ送信用ストリームを解放する
    _writer.Release();

    if (error == SFERR_NO_ERROR) {

        // データ受信用ストリームを取得する
        // ※ size 引数を指定していないのでストリームバッファは可変長
        if ((error = _socket.GetStreamReader(&_reader)) == SFERR_NO_ERROR) {

            // フェッチを行う: 実際にソケットからストリームバッファにデータを受信する
            // ※1. データ受信(フェッチ)の結果は、OnFetch 関数に通知される
            // ※2. 可変長バッファストリームの場合、1 回の Fetch 関数呼び出しでデータ受信は完了する
            // ※3. 受信するデータのサイズに合わせてバッファは自動的に拡張される
            if ((error = _reader.Fetch(XALLBACK_INTERNAL(OnFetch))) != SFERR_NO_ERROR) {

                // エラーが発生したとき
               _reader.Release(); 
            }
        }
    }
    if (error != SFERR_NO_ERROR) { 

        // エラーが発生したとき
        _socket.Close();
    }
    return;
}

// データ受信(フェッチ)の結果が通知されるコールバック関数
XALLBACK_IMPLEMENT_SFXANSISTRINGSTREAMREADER(MyClass, OnFetch, error)
{
    SFXAnsiString string;

    if (error == SFERR_NO_ERROR) {

        // ストリームバッファから string 変数にデータを読み込む
        _reader >> string;

        // string 変数の内容をデバッグウィンドウに表示する
        TRACE("%s", string.GetCString());
    }

    // 受信が終わったのでデータ受信用ストリームを解放する
    _reader.Release();

    // ソケットを閉じる
    _socket.Close();
    return;
}
[Note] 可変長バッファストリームによる TCP ソケット通信

ストリームにはバッファがあります。

SFXTCPSocket::GetStreamReader / SFXTCPSocket::GetStreamWriter 関数で size 引数を指定せずにデータ送受信用ストリームを取得しているので、 可変長バッファが使用されます。 このため、ストリームバッファに送受信する全データと同じサイズまで拡張されます。

SFXAnsiStringStreamWriter::WriteSFXAnsiString 関数は、 string 変数のデータをストリームバッファに書き込みます。

SFXAnsiStringStreamReader::ReadSFXAnsiString 関数は、 ストリームバッファからデータを読み込み、string 変数に格納します。

SFXStreamWriter::Flush 関数は、 ストリームバッファ内のデータを TCP ソケット通信ネットワークに送信します。

SFXStreamReader::Fetch 関数は、 TCP ソケット通信ネットワークからデータを受信し、ストリームバッファに読み込みます。