■ HTTPを扱うためのライブラリ BeOSらしいコードの練習がてら作ってみました。 やはりHTTPが手軽に扱えないとなにかと不便ですし。 特徴としては、非同期な読み込みをサポートする非同期メソッドと、 Translatorなどにそのまま使えるBPositionIOを継承した同期メソッドを持っている点があげられます。
非同期メソッドは、WinSockの非同期モードに近い感じで、関数は常にブロックせずに返ります。 その後コンストラクタで指定されたBLooperオブジェクトに対し、逐次状況をメッセージとして 通達します。読み込み状況を逐次画面に反映させたい場合や、パフォーマンスを細かくコントロール したい場合に有効です。
同期メソッドは、通常のファイル読み込みと同様な気軽さで使えるのが特徴です。Seekも使えます。 読み込みが完了していないデータを読もうとした場合には、読み込み側のスレッドは、必要な部分の データが届くまで一時的にブロックします。BPositionIOを継承しているので、Translatorに そのまま渡せるので、ウェブ上の画像を直接Translatorで展開するなどといった使い方ができます。
◆非同期モードのサンプル細かい処理が多いのと、実行順序が非直線的なのとで、若干複雑に感じるかもしれません。
[http_test1.cpp]
#include <Be.h> #include "TxBTcpHttp.h" // 非同期モデル class MyApp: public BApplication{ private: TxBTcpHttp *http; public: MyApp(void): BApplication("application/x-vnd.toyoshima-house.http_test1"), http(NULL) { }; ~MyApp(void) { if (NULL != http) delete http; } virtual void ReadyToRun(void) { http = new TxBTcpHttp(this); http->SetUserAgent("HTTP Test Client / BeOS"); http->SetServer("www.be.com", 80); http->Get("/"); }; virtual void DispatchMessage(BMessage *msg, BHandler *target) { switch (msg->what) { case TxB_HTTP_NOTIFY: int8 type; if (B_OK != msg->FindInt8(TxB_HTTP_NOTIFY_TYPE, &type)) break; switch (type) { case TxB_HTTP_ERROR:{ int32 code; const char *str; msg->FindInt32(TxB_HTTP_NOTIFY_ERRNO, &code); msg->FindString(TxB_HTTP_NOTIFY_MESSAGE, &str); printf("Error %d: %s\n", code, str); Quit();} case TxB_HTTP_HOST_RESOLVED:{ int32 addr; int16 port; msg->FindInt32(TxB_HTTP_NOTIFY_ADDRESS, &addr); msg->FindInt16(TxB_HTTP_NOTIFY_PORT, &port); printf("Connecting %d.%d.%d.%d:%d ... ", (addr >> 24) & 0xff, (addr >> 16) & 0xff, (addr >> 8) & 0xff, addr & 0xff, port); fflush(stdout); break;} case TxB_HTTP_CONNECTED: puts("Connected"); break; case TxB_HTTP_STATUS:{ int16 status; const char *str; msg->FindInt16(TxB_HTTP_NOTIFY_STATUS, &status); msg->FindString(TxB_HTTP_NOTIFY_MESSAGE, &str); printf("Status: %d %s\n", status, str); break;} case TxB_HTTP_HEADER_COMPLETE: puts("Header Complete"); break; case TxB_HTTP_CONTENT_LENGTH:{ int32 length; msg->FindInt32(TxB_HTTP_NOTIFY_LENGTH, &length); printf("Content-Length: %d\n", length); break;} case TxB_HTTP_COMPLETE:{ int32 length; msg->FindInt32(TxB_HTTP_NOTIFY_LENGTH, &length); printf("Complete: %d\n", length); char *buffer = new char[length + 1]; size_t slen = length; if (NULL != buffer) { http->AsyncRead(buffer, slen); buffer[length] = 0; puts(buffer); } Quit();} case TxB_HTTP_BUFFER_CHANGED:{ int32 newby; int32 current; int32 length = -1; msg->FindInt32(TxB_HTTP_NOTIFY_NEWBY, &newby); msg->FindInt32(TxB_HTTP_NOTIFY_CURRENT, ¤t); msg->FindInt32(TxB_HTTP_NOTIFY_LENGTH, &length); printf("Read %d bytes: %d/%d\n", newby, current, length); break;} } break; default: BApplication::DispatchMessage(msg, target); break; } }; }; int main(int argc, char **argv) { MyApp app; return app.Run(); }
◆同期モードのサンプルこちらは非常に簡単です。たったこれだけのコードでウェブ上の画像ファイルを表示することができます。 Javaでもここまで簡単には書けないでしょ(笑)。
[http_test2.cpp]
#include <Be.h> #include "TxBTcpHttp.h" // 同期モデル class MyApp2: public BApplication{ public: MyApp2(void): BApplication("application/x-vnd.toyoshima-house.http_test2") { }; virtual void ReadyToRun(void) { // まず読み込みを開始させておくと効率的 TxBTcpHttp *http = new TxBTcpHttp(); http->SetServer("www.tk.xaxon.ne.jp", 80); http->Get("/~toyoshim/cg/title_mai.jpg"); // 表示用の窓を準備 BWindow *win = new BWindow(BRect(100, 100, 100 + 320, 100 + 240), "HTTP TEST 2", B_TITLED_WINDOW, B_NOT_RESIZABLE); BView *view = new BView(win->Bounds(), "graphic", B_FOLLOW_ALL_SIDES, B_WILL_DRAW); win->AddChild(view); // BPositionIOとしてTranslatorにぶち込む BBitmap *bmp = BTranslationUtils::GetBitmap(http); delete http; // 窓にペタ! view->SetViewBitmap(bmp); win->Show(); }; }; int main(int argc, char **argv) { MyApp2 app; return app.Run(); }
◆ダウンロードとりあえず、公開しときます。いきなり修正するかもしれませんが、 仕様を変えることはないと思います。自分自身使い回すんで(笑)。 ライセンスはArtisticあたりにしておきます。質問・要望は歓迎。 改善したコードはもっと歓迎。