前のページ次のページ上に戻るホーム BREW C++ ライブラリ & GUI フレームワーク & XML ミドルウェア : SophiaFramework 4.1

16.2. HTTP 接続

16.2.1. HTTP 接続クラス

SFXHTTPConnection は HTTP / HTTPS 通信のためのクラスです。

HTTP / HTTPS 通信は、SFXHTTPConnection クラスを使って以下の手順で行います。

  1. SFXHTTPConnection クラスのインスタンスを作成します。
  2. SFXHTTPConnection::Open 関数を呼び出して、HTTP / HTTPS 接続をオープンします。
  3. SFXHTTPConnection::SetMethod 関数を呼び出して、HTTP リクエスト メソッドを設定します。(デフォルト: GET メソッド) SFXHTTPConnection::GetStreamWriter 関数で出力ストリームを取得しリクエスト ボディにデータを書き込みます。 (※ SFXHTTPConnection::SetRequestHeader 関数でリクエスト ヘッダーを設定することも可能です。)
  4. HTTPS 接続の場合、 SFXHTTPConnection::SetTrustMode 関数を呼び出して、検証モードを設定します。(デフォルト: SSL_TRUST_MODE_FAIL )
  5. SFXHTTPConnection::Connect 関数を呼び出して、Web サーバーに接続します。 接続する URL と、Web サーバーへの接続の通知を受け取るコールバック関数を登録します。
  6. Web サーバーへの接続の通知を受け取ると、SFXHTTPConnection::Connect 関数で登録したコールバック関数が呼び出されます。 Web サーバーへの接続の結果(エラー コード)は、コールバック関数の第 1 引数に渡されます。 エラー コードが SFERR_NO_ERROR であれば、HTTP レスポンスの取得に成功しています。
  7. SFXHTTPConnection::GetResultCode 関数で HTTP ステータス コードを取得し、その内容を確認してから、 SFXHTTPConnection::GetStreamReader 関数で入力ストリームを取得してレスポンス ボディを読み取ります。 (※ SFXHTTPConnection::GetResponseHeader 関数でレスポンス ヘッダーの内容を取得することも可能です。)
  8. 2. から 7. のデータ送受信処理を繰り返します。
  9. 最後に、SFXHTTPConnection::Close 関数を呼び出して、HTTP / HTTPS 接続をクローズします。
[Caution] mif ファイルの設定

mif ファイルの特権レベル設定で「Webアクセス」または「ネットワーク」の項目をオンにします。

16.2.2. GET メソッドによるテキスト データの受信

例 16.5. GET メソッドによるテキスト データの受信

// コールバック関数で使うので、HTTP / HTTPS 通信に必要な SFXHTTPConnection クラスのインスタンス _http はクラスのメンバ変数として定義する
class MyClass {
private:
    SFXHTTPConnection _http;
    SFXAnsiStringStreamReader _reader;
    SFXAnsiString _receivedString;
public:
    Void Start(Void);
    Void SaveToFile(SFXPathConstRef path, SFXAnsiStringConstRef string);
    CALLBACK_DECLARE_SFXHTTPCONNECTION(OnConnect)
    CALLBACK_DECLARE_SFXANSISTRINGSTREAMREADER(OnFetch)
};

Void MyClass::Start(Void)
{
    SFCError error(SFERR_NO_ERROR);

    // GET メソッドでアクセスする
    if ((error = _http.Open()) == SFERR_NO_ERROR) {

        // 接続を開始する
#if 1
        // HTTP 接続の場合
        // 接続の完了は、OnConnect 関数に通知される
        if ((error = _http.Connect("http://www.example.com/",
                         CALLBACK_FUNCTION(OnConnect))) == SFERR_NO_ERROR) {
#else
        // HTTPS 接続の場合
        // 必要に応じて検証モードを設定する
        // 接続の完了は、OnConnect 関数に通知される
        _http.SetTrustMode(SSL_TRUST_MODE_FAIL);
        if ((error = _http.Connect("https://www.example.com/",
                         CALLBACK_FUNCTION(OnConnect))) == SFERR_NO_ERROR) {
#endif
            TRACE("> connecting...");
        }
    }

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

// 接続の完了が通知されるコールバック関数
CALLBACK_IMPLEMENT_SFXHTTPCONNECTION(MyClass, OnConnect, error)
{
    TRACE("> connected... : %d", error);

    if (error == SFERR_NO_ERROR) {

        // HTTP ステータス コードを検査する
        TRACE("> result code : %d", _http.GetResultCode());

        if (_http.GetResultCode() == 200) {

            // データ受信用ストリームを取得する
            if ((error = _http.GetStreamReader(1024, &_reader))
                == SFERR_NO_ERROR) {

                // データを受信する。データ受信の完了は、OnFetch 関数に通知される
                if ((error = _reader.Fetch(CALLBACK_FUNCTION(OnFetch)))
                    == SFERR_NO_ERROR) {
                    TRACE("> fetching...");
                }
            }
        }
        else {
            error = SFERR_INVALID_STATE;
        }
    }

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

// データ受信の完了が通知されるコールバック関数
CALLBACK_IMPLEMENT_SFXANSISTRINGSTREAMREADER(MyClass, OnFetch, error)
{
    SFXAnsiString string;

    TRACE("> fetched... : %d", error);

    if (error == SFERR_NO_ERROR) {

        // データ受信用ストリームからデータを取得する
        if ((error = _reader.ReadSFXAnsiString(&string)) == SFERR_NO_ERROR) {

            // 断片化されたデータを結合する
            if ((error = _receivedString.Add(string)) == SFERR_NO_ERROR) {

                // 残りのデータをチェックする
                if (_reader.Ends()) {

                    // すべてのデータが受信できたので表示する
                    TRACE("--------");
                    TRACE("%s", _receivedString.GetCString()); // (*)
                    TRACE("--------");

                    // 明示的にリソースを解放する
                    _reader.Release();
                    _http.Close();
                }
                else {

                    // データを受信する。データ受信の完了は、OnFetch 関数に通知される
                    error = _reader.Fetch(CALLBACK_FUNCTION(OnFetch));
                }
            }
        }
    }

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

受信したデータをファイルに保存するには、(*) で以下の関数を呼びます。

例 16.6. 受信したデータをファイルに保存する

// 文字列 string をファイルに保存する ( path : ファイルパス )
Void MyClass::SaveToFile(SFXPathConstRef path, SFXAnsiStringConstRef string)
{
    SFCError error;

    SFXFile file;                     // SFXFile クラスのインスタンス
    SFXAnsiStringStreamWriter writer; // ファイル出力用出力ストリーム

    // 読み書きモードでファイルをオープンする
    if ((error = file.OpenReadWrite(path))
        == SFERR_NO_ERROR) {

        // ファイル出力用ストリームの取得
        if ((error = file.GetStreamWriter(string.GetLength(), &writer))
            == SFERR_NO_ERROR) {

            // ファイル出力用ストリームに string を書き込む
            writer.WriteSFXAnsiString(string);

            // 実際に string をファイルに書き込む(Flush 関数を呼び出さないかぎり、ファイルに書き込まれない)
            error = writer.Flush();

            // ファイル出力用ストリームを解放する
            writer.Release();
        }

        // ファイルを閉じる
        file.Close();
    }

    if (error != SFERR_NO_ERROR) {
        // エラー処理
    }
}
[Caution] SFXHTTPConnection のインスタンス

コールバックが戻る前に SFXHTTPConnection のインスタンスが解放されると正しく動作しません。

16.2.3. POST メソッドによるテキスト データの受信

例 16.7. POST メソッドによるテキスト データの受信

// コールバック関数で使うので、SFXHTTPConnection クラスのインスタンス _http はクラスのメンバ変数として定義する
class MyClass {
private:
    SFXHTTPConnection _http;
    SFXAnsiStringStreamReader _reader;
    SFXAnsiString _receivedString;
public:
    Void Start(Void);
    CALLBACK_DECLARE_SFXHTTPCONNECTION(OnConnect)
    CALLBACK_DECLARE_SFXANSISTRINGSTREAMREADER(OnFetch)
};

Void MyClass::Start(Void)
{
    SFXAnsiStringStreamWriter writer;
    SFXAnsiString send;
    SFCError error(SFERR_NO_ERROR);

    unused(environment);

    // POST メソッドでアクセスする
    if ((error = _http.Open()) == SFERR_NO_ERROR) {

        // 送信するデータを用意する
        send = "abcdefghijklmnopqrstuvwxyz";

        // データ送信用ストリームを取得する
        if ((error = _http.GetStreamWriter(send.GetLength(), &writer))
            == SFERR_NO_ERROR) {

            // データを書き込む
            if ((error = writer.WriteSFXAnsiString(send)) == SFERR_NO_ERROR) {

                // 実際にデータを送信する(Flush 関数を呼び出さないかぎり、データは送信されない)
                if ((error = writer.Flush()) == SFERR_NO_ERROR) {

                    // リクエスト メソッドを POST に設定する
                    if ((error = _http.SetMethod("POST")) == SFERR_NO_ERROR) {

#if 1
                        // HTTP 接続の場合
                // 接続の完了は、OnConnect 関数に通知される
                        if ((error = _http.Connect("http://www.example.com",
                            CALLBACK_FUNCTION(OnConnect))) == SFERR_NO_ERROR) {
#else
                        // HTTPS 接続の場合
                        // 必要に応じて検証モードを設定する
                // 接続の完了は、OnConnect 関数に通知される
                        _http.SetTrustMode(SSL_TRUST_MODE_FAIL);
                        if ((error = _http.Connect("https://www.example.com",
                            CALLBACK_FUNCTION(OnConnect))) == SFERR_NO_ERROR) {
#endif
                            TRACE("> connecting...");
                        }
                    }
                }
            }
        }
    }

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

// 接続の完了が通知されるコールバック関数
CALLBACK_IMPLEMENT_SFXHTTPCONNECTION(MyClass, OnConnect, error)
{
    TRACE("> connected... : %d", error);

    if (error == SFERR_NO_ERROR) {

        // HTTP ステータス コードを検査する
        TRACE("> result code : %d", _http.GetResultCode());

        if (_http.GetResultCode() == 200) {

            // データ受信用ストリームを取得する
            if ((error = _http.GetStreamReader(1024, &_reader))
                == SFERR_NO_ERROR) {

                // データを受信する。データ受信の完了は、OnFetch 関数に通知される
                if ((error = _reader.Fetch(CALLBACK_FUNCTION(OnFetch)))
                    == SFERR_NO_ERROR) {
                    TRACE("> fetching...");
                }
            }
        }
        else {
            error = SFERR_INVALID_STATE;
        }
    }

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

// データ受信の完了が通知されるコールバック関数
CALLBACK_IMPLEMENT_SFXANSISTRINGSTREAMREADER(MyClass, OnFetch, error)
{
    SFXAnsiString string;

    TRACE("> fetched... : %d", error);

    if (error == SFERR_NO_ERROR) {

        // データ受信用ストリームからデータを取得する
        if ((error = _reader.ReadSFXAnsiString(&string)) == SFERR_NO_ERROR) {

            // 断片化されたデータを結合する
            if ((error = _receivedString.Add(string)) == SFERR_NO_ERROR) {

                // 残りのデータをチェックする
                if (_reader.Ends()) {

                    // すべてのデータが受信できたので表示する
                    TRACE("--------");
                    TRACE("%s", _receivedString.GetCString());
                    TRACE("--------");

                    // 明示的にリソースを解放する
                    _reader.Release();
                    _http.Close();
                }
                else {

                    // データを受信する。データ受信の完了は、OnFetch 関数に通知される
                    error = _reader.Fetch(CALLBACK_FUNCTION(OnFetch));
                }
            }
        }
    }
	
    if (error != SFERR_NO_ERROR) {
        // エラーが発生したとき
        _reader.Release();
        _http.Close();
    }
    return;
}

16.2.4. バイナリ データの受信

例 16.8. バイナリ データの受信

// コールバック関数で使うので、SFXHTTPConnection クラスのインスタンス _http はクラスのメンバ変数として定義する
class MyClass {
private:
    SFXHTTPConnection _http;
    SFXFile _file;
    SFXBinaryStreamReader _reader; // HTTP 通信でのデータ受信用ストリーム
    SFXBinaryStreamWriter _writer; // ファイル書き込み用ストリーム
    SFXBuffer _receivedBuffer;     // 受信データを格納するバッファ
    SFXBuffer _tempBuffer;         // 受信データを一時的に格納するバッファ
    UInt32 _bufferSize;            // ファイル書き込み用ストリームのバッファ サイズ
public:
    Void Start(Void);
    CALLBACK_DECLARE_SFXHTTPCONNECTION(OnConnect)
    CALLBACK_DECLARE_SFXANSISTRINGSTREAMREADER(OnFetch)
};

Void MyClass::Start(Void)
{
    SFCError error(SFERR_NO_ERROR);

    // バッファサイズを設定する
    _bufferSize = 1024;

    // バッファを確保する
    if ((error = _tempBuffer.SetSize(_bufferSize)) == SFERR_NO_ERROR) {

        // ファイルをオープンする
        if ((error = _file.OpenReadWrite(SFXPath("/example.dat")))
            == SFERR_NO_ERROR) {

            // ファイル書き込み用ストリームを取得する
            if ((error = _file.GetStreamWriter(_bufferSize, &_writer))
                == SFERR_NO_ERROR) {

                // GET メソッドでアクセスする
                if ((error = _http.Open()) == SFERR_NO_ERROR) {
				
#if 1
                    // HTTP 接続の場合
              // 接続の完了は、OnConnect 関数に通知される
                    if ((error = _http.Connect("http://www.example.com",
                                 CALLBACK_FUNCTION(OnConnect))) == SFERR_NO_ERROR) {
#else
                    // HTTPS 接続の場合
                    // 必要に応じて検証モードを設定する
              // 接続の完了は、OnConnect 関数に通知される
                    _http.SetTrustMode(SSL_TRUST_MODE_FAIL);
                    if ((error = _http.Connect("https://www.example.com",
                                 CALLBACK_FUNCTION(OnConnect))) == SFERR_NO_ERROR) {
#endif
                       TRACE("> connecting...");
                    }
                }

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

// 接続の完了が通知されるコールバック関数
CALLBACK_IMPLEMENT_SFXHTTPCONNECTION(MyClass, OnConnect, error)
{
    TRACE("> connected... : %d", error);

    if (error == SFERR_NO_ERROR) {

        // HTTP ステータス コードを検査する
        TRACE("> result code : %d", _http.GetResultCode());

        if (_http.GetResultCode() == 200) {

            // データ受信用ストリームを取得する
            if ((error = _http.GetStreamReader(_bufferSize, &_reader))
                == SFERR_NO_ERROR) {

                // データを受信する。データ受信の完了は、OnFetch 関数に通知される
                if ((error = _reader.Fetch(CALLBACK_FUNCTION(OnFetch)))
                    == SFERR_NO_ERROR) {
                    TRACE("> fetching...");
                }
            }
        }
        else {
            error = SFERR_INVALID_STATE;
        }
    }

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

// データ受信の完了が通知されるコールバック関数
CALLBACK_IMPLEMENT_SFXANSISTRINGSTREAMREADER(MyClass, OnFetch, error)
{
    TRACE("> fetched... : %d", error);

    if (error == SFERR_NO_ERROR) {

        // 一時バッファサイズを再度設定する
        _tempBuffer.SetSize(_reader.GetReadableSize());

        // データ受信用ストリームからデータを取得する
        if ((error = _reader.Read(&_tempBuffer)) == SFERR_NO_ERROR) {

            // ファイルに書き込む
            // ( 正確には、ファイル書き込み用ストリームのバッファに書き込む )
            if ((error = _writer.Write(_tempBuffer)) == SFERR_NO_ERROR) {

                // 実際にファイルに書き込む
              // 実際に string をファイルに書き込む(Flush 関数を呼び出さないかぎり、ファイルに書き込まれない)
                if ((error = _writer.Flush()) == SFERR_NO_ERROR) {

                    // 断片化されたデータを結合する
                    if ((error = _receivedBuffer.Add(_tempBuffer))
                        == SFERR_NO_ERROR) {

                        // 残りのデータをチェックする
                        if (_reader.Ends()) {

                            // すべてのデータが受信できたので表示する
                            TRACE("--------");
                            TRACE("%s", _receivedBuffer.GetBuffer());
                            TRACE("--------");

                            // 明示的にリソースを解放する
                            _reader.Release();
                            _http.Close();
                            _writer.Release();
                            _file.Close();
                        }
                        else {
                            // データを受信する。データ受信の完了は、OnFetch 関数に通知される
                            error = _reader.Fetch(CALLBACK_FUNCTION(OnFetch));
                        }
                    }
                }
            }
        }
    }
	
    if (error != SFERR_NO_ERROR) {
        // エラーが発生したとき
        _reader.Release();
        _http.Close();
        _writer.Release();
        _file.Close();
    }
    return;
}

データの受信と同時にファイルにも保存します。 ( テキスト、バイナリの両方に対応 )

16.2.5. HTTP 通信でのファイルのアップロード

以下のコードを使って、ファイルを HTTP サーバーへアップロードします。

[Caution] ファイル サイズ制限

このコードではサイズの大きな ( 100k バイト程度以上 ) ファイルを転送できません。

例 16.9. HTTP 通信でのファイルのアップロード

// コールバック関数で使うので、SFXHTTPConnection クラスのインスタンス _http はクラスのメンバ変数として定義する
class MyClass {
private:
    SFXHTTPConnection _http;
    SFXAnsiStringStreamReader _reader;
    SFXAnsiString _receivedString;
public:
    Void Start(Void);
    CALLBACK_DECLARE_SFXHTTPCONNECTION(OnConnect)
    CALLBACK_DECLARE_SFXANSISTRINGSTREAMREADER(OnFetch)
};

Void MyClass::Start(Void)
{
    SFXFile file;
    SFXBinaryStreamReader reader;
    SFXBinaryStreamWriter writer;
    SFXBuffer buffer;
    SFCError error(SFERR_NO_ERROR);

    // SFXHTTPConnection をオープンする
    if ((error = _http.Open()) == SFERR_NO_ERROR) {

        // SFXFile をオープン
        if ((error = file.OpenReadOnly(SFXPath("/data.txt"))) == SFERR_NO_ERROR) {

            // データ送信用ストリームを取得する
            if ((error = _http.GetStreamWriter(1024, &writer))
                == SFERR_NO_ERROR) {

                // ファイル読み込み用ストリームを取得する
                if ((error = file.GetStreamReader(1024, &reader))
                    == SFERR_NO_ERROR) {

                    // ファイル読み込み用ストリームから データ送信用ストリームへデータをコピーする
                    while (error == SFERR_NO_ERROR) {
                        if ((error = reader.Fetch()) == SFERR_NO_ERROR) {
                        
                            // ファイル読み込み用ストリームからデータを読み込むためのバッファを確保する
                            if ((error = buffer.SetSize(
                                reader.GetReadableSize())) == SFERR_NO_ERROR) {

                                // ファイル読み込み用ストリームからデータを読み込む
                                if ((error = reader.Read(&buffer))
                                    == SFERR_NO_ERROR) {
                                    
                                    // データ送信用ストリームへデータを書き込む
                                    if ((error = writer.Write(buffer))
                                        == SFERR_NO_ERROR) {
                                        // 実際にデータを送信する(Flush 関数を呼び出さないかぎり、データは送信されない)
                                        if ((error = writer.Flush())
                                            == SFERR_NO_ERROR) {
                                            
                                            // ファイル読み込み用ストリームの終端のとき、ループを抜ける
                                            if (reader.Ends()) {
                                                break;
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }

                    // 正常にコピーできたとき
                    if (error == SFERR_NO_ERROR) {

                        // リクエスト メソッドを POST に設定する
                        if ((error = _http.SetMethod("POST")) == SFERR_NO_ERROR) {

                            // 接続を開始する
#if 1
                            // HTTP 接続の場合
                      // 接続の完了は、OnConnect 関数に通知される
                            if ((error = _http.Connect("http://www.example.com",
                                CALLBACK_FUNCTION(OnConnect)))
                                == SFERR_NO_ERROR) {
#else
                            // HTTPS 接続の場合
                            // 必要に応じて検証モードを設定する
                      // 接続の完了は、OnConnect 関数に通知される
                            _http.SetTrustMode(SSL_TRUST_MODE_FAIL);
                            if ((error = _http.Connect("https://www.example.com",
                                CALLBACK_FUNCTION(OnConnect)))
                                == SFERR_NO_ERROR) {
#endif
                                TRACE("> connecting...");
                            }
                        }
                    }
                }
            }
        }
    }
	
    if (error != SFERR_NO_ERROR) {
        // エラーが発生したとき
        _http.Close();
    }
}

// 接続の完了が通知されるコールバック関数
CALLBACK_IMPLEMENT_SFXHTTPCONNECTION(MyClass, OnConnect, error)
{
    TRACE("> connected... : %d", error);

    if (error == SFERR_NO_ERROR) {

        // HTTP ステータス コードを検査する
        TRACE("> result code : %d", _http.GetResultCode());

        if (_http.GetResultCode() == 200) {

            // データ受信用ストリームを取得する
            if ((error = _http.GetStreamReader(1024, &_reader))
                == SFERR_NO_ERROR) {

                // データを受信する。データ受信の完了は、OnFetch 関数に通知される
                if ((error = _reader.Fetch(CALLBACK_FUNCTION(OnFetch)))
                    == SFERR_NO_ERROR) {
                    TRACE("> fetching...");
                }
            }
        }
        else {
            error = SFERR_INVALID_STATE;
        }
    }
	
    if (error != SFERR_NO_ERROR) {
       // エラーが発生したとき
       _http.Close();
    }
    return;
}

// データ受信の完了が通知されるコールバック関数
CALLBACK_IMPLEMENT_SFXANSISTRINGSTREAMREADER(MyClass, OnFetch, error)
{
    SFXAnsiString string;

    TRACE("> fetched... : %d", error);

    if (error == SFERR_NO_ERROR) {
        // データ受信用ストリームからデータを取得する
        if ((error = _reader.ReadSFXAnsiString(&string)) == SFERR_NO_ERROR) {

            // 断片化されたデータを結合する
            if ((error = _receivedString.Add(string)) == SFERR_NO_ERROR) {

                // 残りのデータをチェックする
                if (_reader.Ends()) {

                    // すべてのデータが受信できたので表示する
                    TRACE("--------");
                    TRACE("%s", _receivedString.GetCString());
                    TRACE("--------");

                    // 明示的にリソースを解放する
                    _reader.Release();
                    _http.Close();
                }
                else {

                    // データを受信する。データ受信の完了は、OnFetch 関数に通知される
                    error = _reader.Fetch(CALLBACK_FUNCTION(OnFetch));
                }
            }
        }
    }
	
    if (error != SFERR_NO_ERROR) {
        // エラーが発生したとき
        _reader.Release();
        _http.Close();
    }
    return;
}