2025 02,02 14:18 |
|
× [PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。 |
|
2008 12,14 17:05 |
|
WInInet API を使ってサイトのコンテンツをダウンロードしてくる場合、リクエスト情報に Accept-Encoding を付加すると gzip (deflate 圧縮に gz ヘッダー情報がついたもの) されて送られてきます。
圧縮ファイルの解凍ツールは沢山あるのですが、Win32プログラムで使える API があまりありません。 zlib を ダウンロードしてきて zlib.h, zconf.h を StockPrice のプロジェクトに加えて使っています。 最初 uncompress が一番簡単そうに思えたので使ってみたのですが DATAERROR -3 が戻るのみでうまく動きません。受け取ったデータをファイルに全部書き出して "aaa.gz" とか名前を付けてPC上で解凍すると見事に解凍出来ました。データが壊れているわけではなさそうです。 uncompress のソースを読み始めると結局は infalte でゴリゴリ書いてあるだけで、自分で書いても同じ事かなとあきらめかけたのですが、ファイル解凍用の gz_open ではななんと inflateInit2 の windowbits 引数で-MAX_WBITSが指定されている事に気付きました。 注意しないといけないところ、はまるところは inflateInit2 はマクロなので実際に呼ばれている API の inflateInit2_ を GetProcessAddress で呼び込まないといけないことです。 かなり添付ソースでは端折って書いてあります。 まじめに汎用として使うには StockPriceでみているサイトから送られる gz ヘッダーはいつも10バイトなので、10バイトスキップ とかしています。本来は可変長のヘッダーのようですから、例えば該当フラッグビットが1ならそのサイズを取り出してサイズ分コメントを読み飛ばすみたいな事が必要です。 また、複数回にわけて解凍する場合には出力バッファがいっぱいになったら。。。とかコードを入れる必要があります。ここでは1回で解凍していますから端折っています。 いつでも動き始めると簡単でなんで。。。なんで。。。ですが、動くようになるまでが大変です。 全然関係無い話ですが、 昔 Unix のポーティングをしていたときに覚えたのですが、zlib のソースを読んでいて思い出しました。 fopen、fread、fwrite といった f 系の関数に渡すファイルポインタって io_stream 構造体のアドレスなんですね。。。 Unix のソースは読んでいて本当に飽きないですよね。大袈裟ですが人類の英知というか、そうか成程へーっ!みたいな感じです。 ソースです。 PR |
|
2008 12,14 16:02 |
|
2008 12,13 12:29 |
|
InternetConnect で取得したハンドル hConnect を使って色々な要求を出します。
その要求の方式”GET”、”POST”だとかを lpszVerb に、サーバー側のどのオブジェクトに対するリクエストかを lpszObjectName に記述してゆきます。”GET" Method を指定している場合には - サーバー側のどのプログラムを起動し、?でSymbol=Value の形でプログラムに渡すパラメータとその値を記述します。urlencode する必要がありますが StockPrice&Chart では渡すフォーマットが決まっていますから”/”、”:”は直接”%2F”とか”%3A”として設定しています。 PPC、WMでは内部は Widechar が標準のため Multibyte に変換しています。 RequestHeader に指定する情報を一度に複数指定できないので、HttpAddRequestHeaders で一つずつ指定してゆきます。ここでは指定する文字列は"\r\n"のペアで終端する必要があります。 "Accept-Encoding: gzip, inflate\r\n" はデバイスの”¥Windows”の下に zlib1.dll がある場合、gzip、inflate のフォーマットで圧縮して送るよう指示するための指定です。 zlib を使った解凍が今朝4:00前に動くようになったので別トピックに書きます。 ”POST” method を指示した場合のパラメータは HttpSendRequest の lpOptional に "Symbol=Value" で記述して”&”でつないで一つの文字列にして渡します。ここでもurlencodeが必要です。 一つのリクエストが終わって結果をすべて受け取ると次のリクエストを投げます。ただ次のリクエストを投げる前に一旦 hRequest をクローズしないとサーバーの応答がなかったのでクローズを毎回挟んでいます。 正常にリクエストを出して正常に結果を受け取っている間はリクエストを投げてクローズの繰り返しですが、エラーを検出した場合や回線の切断を行った場合 "InternetOpen" から実行するようにしています。 ”POST”の場合に必要なパラメータは Fiddler2 を使ってIEの実際のページからデータを取得して見つけています。 ソースです。 |
|
2008 12,10 00:41 |
|
ここで使っているCallBackのソースを掲載しておきます。オリジナル(ほとんど変えていませんが)ではコンソールアプリのためデバッグ・メッセージをコンソール出力していますが、それをはずしたものを使っています。
BUG: Error 12019 When Calling InternetWriteFileというトピックのマイクロソフト・サポートオンラインからダウンロードしてきたものです。 dwContext で渡ってきた1、2で見るステータスや、シグナルするイベントを変えています。 それにしてもWInInetのAPIを使ったAsync/POSTのサンプルや解説が少ないです。 |
|
2008 12,07 22:10 |
|
InternetOpenで返ってきたハンドルでそこにどんなプロトコル(HTTPなのかFTPなのか)を流すかここで定義します。ここでは認証のためのユーザー名パスワードも指定できるようになっていますが、StockPrice&Chartでは不要なのでNULLを指定しています。
dwFlagはFTPを使うときに必要な引数なのでここではNULLです。 dwContextはCallBackルーティンに渡すポインタです。現在ポインタで渡さなければならないほど沢山の情報がないので、ここではCallBackルーティンにInternetConnectで起こったCallBackである事を伝える(1)という値を設定しています。 InnternetConnectを非同期に抜けてきた後 WaitForSingleObject では hConnectedEvent がシグナルされるのを待っているのでCallBack の中ではdwContextポインタが1の場合、Connected の状態になると hConnectedEvent をセットするようになっています。 ソースです。 |
|
忍者ブログ [PR] |