問題タブ [wininet]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
.net - の InternetOpenUrl と InternetReadFile に関するヘルプAPI
WinInet API を使用して単純にページにアクセスしようとしています。アクセスしたら、内容を文字列に読み込めるようにしたいと思います。ルートノードはすでに初期化しています。これが私がこれまでに得たものです:
この後、実際にデータを引き出すには InternetReadFile を利用する必要があることがわかりました。誰かがそれを行う方法の詳細な例を提供できますか? 私は C スタイルのファイル関数とバッファーの使用に特に慣れていないので、気楽にやってください。
別の注意として、代わりに使用する必要がある別の、またはより最新の Windows API はありますか? 長期的には、クライアントとして機能し、リモート サーバーで HTTP および HTTPS を使用してデータを送受信するアプリの開発を任されています。私はここで正しい道を進んでいますか?
編集: 要件についてより具体的に説明するには: C++ で記述されている必要があり、Win XP 以降と互換性があり、標準の Windows ライブラリのみを使用する必要があります。それ以外は自由にやりたい放題です。
c++ - WinINet 非同期モードの惨事
長い質問で申し訳ありません。問題を解決するために数日を費やしただけで、疲れ果てています。
WinINet を非同期モードで使用しようとしています。そして、私は言わなければなりません...これは単に正気ではありません. これは本当に理解できません。非常に多くのことを行いますが、残念ながらその非同期 API の設計は非常に貧弱であるため、高い安定性が要求される本格的なアプリケーションでは使用できません。
私の問題は次のとおりです。多くの HTTP/HTTPS トランザクションを連続して実行する必要がありますが、要求に応じてすぐに中止できる必要もあります。
次の方法で WinINet を使用するつもりでした。
InternetOpen
フラグ付きの関数を介して、WININet の使用を初期化しINTERNET_FLAG_ASYNC
ます。- グローバル コールバック関数をインストールします ( 経由
InternetSetStatusCallback
)。
さて、私がやろうと思っていたトランザクションを実行するために:
- トランザクションの状態を説明するさまざまなメンバーを使用して、トランザクションごとの構造を割り当てます。
- 電話
InternetOpenUrl
して取引を開始します。非同期モードでは、通常、すぐにエラーが返されますERROR_IO_PENDING
。パラメータの 1 つは「コンテキスト」で、コールバック関数に渡される値です。トランザクションごとの状態構造体へのポインターに設定します。 - この直後にグローバル コールバック関数が (別のスレッドから) status で呼び出されます
INTERNET_STATUS_HANDLE_CREATED
。この時点で、WinINet セッション ハンドルを保存します。 INTERNET_STATUS_REQUEST_COMPLETE
トランザクションが完了すると、最終的にコールバック関数が呼び出されます。これにより、何らかの通知メカニズム (イベントの設定など) を使用して、元のスレッドにトランザクションが完了したことを通知できます。- トランザクションを発行したスレッドは、トランザクションが完了したことを認識します。次に、クリーンアップを行います。WinINet セッション ハンドルを (によって
InternetCloseHandle
) 閉じ、状態構造を削除します。
今のところ問題はないようです。
実行中のトランザクションを中止するには? 1 つの方法は、適切な WinINet ハンドルを閉じることです。また、WinINet には次のような機能がないためInternetAbortXXXX
、ハンドルを閉じることが中止する唯一の方法のようです。
確かにこれはうまくいきました。ERROR_INTERNET_OPERATION_CANCELLED
このようなトランザクションは、エラー コードですぐに完了します。しかし、ここからすべての問題が始まります...
私が遭遇した最初の不愉快な驚きは、WinINet が、トランザクションが既に中止された後でも、トランザクションのコールバック関数を呼び出す傾向があることです。MSDN によるとINTERNET_STATUS_HANDLE_CLOSING
、コールバック関数の最後の呼び出しです。しかし、それは嘘です。私が見ているのは、同じハンドルに対する結果通知が時々あるということです。INTERNET_STATUS_REQUEST_COMPLETE
また、トランザクション ハンドルを閉じる直前にコールバック関数を無効にしようとしましたが、これは役に立ちませんでした。WinINet のコールバック呼び出しメカニズムは非同期のようです。したがって、トランザクション ハンドルが閉じられた後でも、コールバック関数を呼び出すことができます。
これには問題があります。WinINetがコールバック関数を呼び出すことができる限り、トランザクション状態構造を解放することはできません。しかし、WinINet が親切にそう呼んでくれるかどうか、どうして私が知ることができるでしょうか? 私が見たところ、一貫性がありません。
それにもかかわらず、私はこれを回避しました。代わりに、割り当てられたトランザクション構造のグローバル マップ (もちろんクリティカル セクションによって保護されています) を保持しています。次に、コールバック関数内で、トランザクションが実際に存在することを確認し、コールバックの呼び出し中にトランザクションをロックします。
しかし、これまで解決できなかった別の問題を発見しました。トランザクションが開始された直後にトランザクションを中止すると発生します。
を呼び出すと、エラー コードInternetOpenUrl
が返されます。ERROR_IO_PENDING
次に、コールバック関数がINTERNET_STATUS_HANDLE_CREATED
通知で呼び出されるまで(通常は非常に短い)待ちます。次に、トランザクション ハンドルが保存されるので、ハンドル/リソース リークなしで中止する機会が得られ、先に進むことができます。
この瞬間の直後に中止を試みました。つまり、このハンドルを受け取ったらすぐに閉じてください。何が起こると思いますか?WinINet がクラッシュします。無効なメモリ アクセスです! これは、コールバック関数で行うこととは関係ありません。コールバック関数は呼び出されません。クラッシュは WinINet の奥深くにあります。
一方、次の通知(「名前の解決」など)を待つと、通常は機能します。しかし、時々クラッシュすることもあります!Sleep
ハンドルを取得してから閉じるまでに最低限のことをすると、問題は解消されるようです。しかし、明らかにこれは深刻な解決策として受け入れられません。
以上のことから、WinINet の設計が不十分であるという結論に達しました。
- 特定のセッション (トランザクション) に対するコールバック関数の呼び出しの範囲について厳密な定義はありません。
- WinINet ハンドルを閉じることができるタイミングについて、厳密な定義はありません。
- 誰が他に何を知っていますか?
私が間違っている?それは私が理解できないものですか?それとも、WinINet を安全に使用できないのでしょうか?
編集:
これは、2 番目の問題であるクラッシュを示す最小限のコード ブロックです。エラー処理などをすべて削除しました。
通常、1 回目または 2 回目の反復でアプリケーションがクラッシュします。WinINet によって作成されたスレッドの 1 つがアクセス違反を生成します。
上記のアドレスは、C++ (少なくとも MSVC) で記述されたコードにとって特別な意味を持つことに注意してください。AFAIK を持つvtable
(つまり、仮想関数を持つ) オブジェクトを削除すると、上記のアドレスに設定されます。そのため、既に削除されたオブジェクトの仮想関数を呼び出そうとしています。
c++ - wininet.dll で一見ランダムにクラッシュする原因は?
wininet.dll の奥深くでクラッシュします。でゼロメモリ位置を読み取ろうとしてクラッシュしましたHTTP_REQUEST_HANDLE_OBJECT::ReleaseConnection
これは実際の DLL のバグであり、不適切な使用によるものではありませんか?
wininet!HTTP_REQUEST_HANDLE_OBJECT::ReleaseConnection+0x60
wininet!HTTP_REQUEST_HANDLE_OBJECT::CloseConnection+0x84
wininet!HTTP_REQUEST_HANDLE_OBJECT::ReadData_Fsm+0x5e8
wininet!CFsm_ReadData::RunSM+0x2e
wininet!CFsm::Run+0x39
wininet!DoFsm+0x25
wininet!HTTP_REQUEST_HANDLE_OBJECT:: ReadData+0x38
wininet!HTTP_REQUEST_HANDLE_OBJECT::HttpReadData_Fsm+0x43
wininet!CFsm_HttpReadData::RunSM+0x2e
wininet!CFsm::Run+0x39
wininet!DoFsm+0x25
wininet!HttpReadData+0x67
wininet!ReadFile_Fsm+0x2d
wininet!CFsm_ReadFile+0x2RunbSM
wininet!CFsm::Run+0x39
wininet!DoFsm+0x25
wininet!InternetReadFile+0x3ca
コンテキストは、ファイルをダウンロードしようとしています。呼んでいます
InternetReadFile (hFile、lpBuffer、dwNumberOfBytesToRead、lpdwNumberOfBytesRead);
hFile HINTERNET ハンドルは問題ないようです (値は 0x00cc0024 であり、正当なようです)。dwNumberOfBytesToRead は 20000 です。
私のバッファ サイズは 131000 ですが、これも問題ありません。
問題は、私のコードが 99.9999% の確率で動作することです!
c# - wininet を使用したプロキシ設定の設定
wininet でプロキシのユーザー名とパスワードを設定する際に問題が発生しています。
次のコードはプロキシを設定しますが、ユーザー名とパスワードはエラー コード "12018" で失敗します
c++ - ファイルをクライアントにダウンロードするときに WinINet で問題が発生しましたか?
なぜこの機能に問題があるのか 知りたいです。Web 上の PNG ファイルを宛先パスにダウンロードしています。たとえば、Google イメージを C: ドライブにダウンロードします。
netDownloadData(" http://www.google.com/intl/en_ALL/images/srpr/logo1w.png ", "c:\file.png");
ダウンロード後のファイルサイズは正しいです。false を返すものはありません。開こうとすると画像が表示されません。どんなアイデアも役に立ちます。ありがとう!
コードは次のとおりです。
multithreading - いつでもダウンロードを中止できる状態で、インターネットからファイルをダウンロードする
ダウンロード専用の別のスレッドで Delphi プログラムからファイルをダウンロードしたいと考えています。
問題は、メイン プログラムがいつでも閉じられる可能性があることです (したがって、ダウンロード スレッドもいつでも終了される可能性があります)。そのため、接続がない場合やサーバーが貴重な数秒間遅延した場合でも、ダウンロード スレッドを 1 ~ 2 秒以内に終了する方法が必要です。
皆さんはどの機能を使うのがオススメですか?
InterOpenURL/InternetReadFile を試してみましたが、タイムアウト パラメータがありません。非同期バージョンはありますが、動作する Delphi の例が見つかりませんでした。また、非同期バージョンがハングから保護してくれるかどうかもわかりません...
以前からソケットの使用を勧められていましたが、TClientSocket にもタイムアウト機能がないようです。
ユーザーのコンピューターでインターネット接続の問題が発生したり、Web サーバーの動作が遅くなったりしても、アプリケーションを閉じる前にハングしないように、十分に準備する必要があります。
サードパーティのコンポーネントも Indy も使用したくないということを回答する際は、心に留めておいてください。サンプルコードは大歓迎です。
ありがとうございました!
c# - IE 新しいセッション C# wininet?
wininet が Web ブラウザー コントロールに強制的に新しいセッションを開始させる方法に関する記事をいくつか見てきました (IE を開いて、[ファイル] に移動し、[新しいセッション] をクリックするのと同じです)。
これは正しいですか、それとも誤解していますか? 可能であれば、誰かが参考資料の方向性を教えてもらえますか?
前もって感謝します。
windows - WinINET は再入可能ですか?
WinHTTP は再入可能ではありません ( 1、2 )。WinINET は再入可能ですか?
WinINET と同期 HTTP を行う ActiveX コントロールがあります。ブラウザー (javascript) が非同期 http 要求 (ajax) を起動し、すぐに ActiveX 操作 (同じ IE プロセス) を呼び出す場合、2 つの操作がインターリーブしているように見えます。おそらく同じ API で再入可能であり、WinINET 状態を壊しています。 ajax の clearInterval が誤って 1 回失敗します。ajax には EXT を使用しており、EXT は clearInterval が初めて機能することを前提としています。
c# - C# wininet InternetSetOption
System.Windows.Forms.WebBrowserセッションデータをクリアする方法を使用していますか? ブラウザが 1 つしかない限り機能します。同じアプリケーション内で 2 つの Web ブラウザ コントロールに独自のセッションを与えることは可能ですか?
だったら変えるしかないか
に
?
それとも他に何か必要ですか?
c++ - アプリからの HTTP リクエストが、送信者のネットワーク/プロキシとウェブ ホストの間で消える
ここで作業するための情報はまだあまりありません。私たちのアプリは HTTP クエリをサーバーに送信します。これまでに使用したすべてのケースで問題なく動作しました。しかし、ネットワークがプロキシを経由している 1 つのクライアントのログは、要求が正常に送信されたことを示していますが、応答は返されず、Web サーバーはログに何かを受信したことを示していません (障害が発生した時間帯)。 、ログに存在するのは、次に説明するように、インストーラー内からの ZIP のダウンロードだけです)。これは、ネットワーク上の誰に対しても一貫して発生します。
奇妙な点の 1 つは、アプリのインストーラーが ZIP ファイルの HTTP 要求を送信し、問題なく完了しますが、アプリの起動時に (PHP ファイルへの) 最初の要求が失敗することです。これらは、要求を行うために使用される同じ基本コードを共有しますが、異なるパラメーターを送信するだけです。私は 2 つの呼び出しの実際の違いを理解しようとしてきましたが、基本的には次のようになります。
- 1 つは zip ファイルを要求するもので、もう 1 つはパラメーターを php ファイルに送信するものです。ファイルタイプフィルタリング?
- 失敗しているものには、いくつかの余分なヘッダー パラメータが追加されています。それらがプロキシによって削除されたかどうかは理解できますが、カスタム/サポートされていないヘッダーがある場合、リクエストを完全にドロップできますか?
関数呼び出しの基本的なスケルトン構造は次のとおりです。
リクエストのどの部分が失敗し、どのエラー コードが返されたかを把握するために、より多くのエラー チェックを提供する新しいビルドをセットアップします。また、カスタム ヘッダーや、これとインストーラーの間のその他の不一致も解消されます。
私はそれが本当に原因であるという確信をあまり持っていないので、それまでの間、何がうまくいかないのか、または再確認または注意すべきことについての推測を探しています. 私は当初、ロックダウンされたネットワークのフィルタリングの問題であると確信していましたが、IT グループと話しているところ、要求はブロックされていません。おそらく、私が行っている非標準的なことがいくつかあります。