問題タブ [iocp]
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.
boost - Boost::AsioのIOCP CompletionKey?
を使用して TCP サーバーを作成していますBoost::Asio
。各クライアントのパケット時間を追跡する必要があります。IO 操作が完了すると、 から返された完了キーを使用して各クライアントを簡単に識別できますGetQueuedCompletionStatus
。でこれを行う方法が見つかりませんBoost::Asio
。
これをどのように実装できますか、または代替手段はありますか?
openssl - AcceptExとOpenSSL
AcceptExとOpenSSLを使用してクライアントからの新しい接続を処理する適切な方法を知りたいです。私は、通常のHTTPを介してIO完了ポートでAcceptExを使用する完全に機能するサーバーを持っています。OpenSSLサポートを追加したいと思います。
ノンブロッキングソケットでのOpenSSLの使用に関するインターネット上のいくつかの記事を読みました。
- IO完了ポートとOpenSSL
- http://zzz.zggg.com/2007/12/22/ssl-server-with-openssl-memory-bio-aka-prerequisite-to-asynchronous-openssl/
- http://marc.info/?l=openssl-users&m=99909952822335&w=2
- http://www.lenholgate.com/blog/2002/11/using-openssl-with-asynchronous-sockets.html
彼らは主に接続のクライアント側に関係しているので、それらのどれもこれを行う方法に触れていないようです。AcceptExはソケット接続を確立し、クライアントから送信された最初のデータを返します。私が投稿した最初のリンクでは、IOCPを使用して受信データを処理する方法について説明しています。私はこれまで運がなかったのでそこに投稿されたものを試しました。基本的に、サーバーに表示されるのは次のとおりです。
- 受け入れられた接続完了が受信されます。
- SSL_new(ctx)を使用してSSLオブジェクトを作成します
- BIO_new(BIO_s_mem())を使用してインおよびアウトのBIOオブジェクトを作成します。
- SSL_set_bio(ssl、bioIn、bioOut)を呼び出して、SSLオブジェクトにBIOを設定します。
- SSL_set_accept_state(ssl)を呼び出して、SSL_readとSSL_writeがネゴシエーションを実行できるようにします。
次に、AcceptEx呼び出しによって読み取られたデータの最初のバッファーの処理を試みます。
- BIO_Write(bioIn、buf、len)を呼び出して、読み取ったデータをSSLにコピーします。
- 次に、bioOutで保留中のハンドシェイクデータをチェックして、それをクライアントに送り返す必要があるかどうかを確認します。新しい接続を受け入れるとき、私はこの時点でbioOutにデータがあるのを見たことがありません。
- 次に、SSL_read(ssl、plainTextBuf、len)を呼び出して、手順6でbioInに入れたデータを復号化しようとします。これは常に-1を返し、SSL_get_errorはERROR_SSL_WANT_READを返します。私が理解しているように、これはbioInが完全なSSLレコードを持っていないことを意味します。したがって、SSLは何かを復号化する前に、クライアントからのより多くのデータを必要とします。
ここで私は問題にぶつかり始めます、そしてそれは私が何らかの方向性を必要とすると思うところです。私は多くのことを試みました。この時点でSSL_readを繰り返し呼び出すと、ERROR_SSL_WANT_READが無限に返されます。これは、メモリを使用すると、BIOが実際にソケットを介して通信してデータを受信しないためと考えられます。クライアントからのより多くのデータを待つために、WSARecv呼び出しを投稿する必要がありますか?
また、この時点でBIO_readを使用してbioOutバッファーをチェックし、クライアントに送り返す必要のあるデータがあるかどうかを確認してみました。確かにいくつかあり、私はWSASendを使用してこれを送り返し、さらにデータを待つために別のWSARecv呼び出しを投稿します(私の送信に応答して)。これにより、クライアントからさらにデータを受信することになり(WSARecvは送信が完了した後に完了します)、接続が進行中であるように見えます。ただし、この完了した読み取りを処理すると、SSL_readとBIO_readの両方がERROR_SSL_WANT_READを返します。そのため、完全なレコードを復号化するのに十分なデータがなく、クライアントに送り返すものがありません。この状況に応じて別のWSARecv呼び出しを送信しても、クライアントからそれ以上のデータを受信することはありません。ここでSSLが何を求めているのかわかりません。
今は行き詰まっていますが、これからも頑張っていきます。何かわかったら、コメントでこの質問を更新します。
windows - CloseHandle()は、シリアルポートが実際に閉じられる前に戻ります
シリアルポートが閉じ終わったときを把握しようとして髪を引っ張っているので、再び開くことができます。CloseHandle()
ポートが実際にロック解除される前に戻ることが判明しました。
を使用してシリアルポートを開き、を使用CreateFile(FILE_FLAG_OVERLAPPED)
してCompletionPortに関連付け、を使用してCreateIoCompletionPort()
読み取り/書き込みを行い、を使用しReadFile()
てWriteFile()
閉じていCloseHandle()
ます。
シリアルポートをすばやく閉じて再度開くと、ERROR_ACCESS_DENIED
から戻ってくることに気づきましたCreateFile()
。CloseHandle()
これは、戻るのを待ってから、そのハンドルに関連付けられているすべての未処理の読み取り/書き込み操作が完了ポートから戻るのを待っているにもかかわらず発生しています。確かにもっと良い方法があります:)
シリアルポートを同期的に閉じるにはどうすればよいですか?ループ、sleep()、またはその他の安価なハックを再試行しないでください。
編集:多分これは私の完了ポートとFILE_FLAG_OVERLAPPEDの使用と関係があります。読み取り/書き込み操作が完了すると、コールバックが返されます。ポートを閉じるための何らかのコールバックはありますか?
windows - マシンごとに同時に開かれるソケット/接続の数に関するWindowsの制限
1つの実際のネットワークインターフェイスといくつかのループバックインターフェイスを備えたWindows7があるとします。クライアントからの接続を受け入れるIOCP対応サーバーがあります。サーバーへの実際のクライアント接続を可能な限りシミュレートしようとしています。
私のクライアントコードは、X個のソケット接続を確立するだけです(クライアントは特定のインターフェイスにバインドすることに注意してください)。
ループバックインターフェイスには、バインディングに使用するIPがいくつかあります。さらに、実際のインターフェイスを使用してバインドします。開いているソケットの数がマシンあたり約64Kの場合、問題が発生しました。
未処理の例外:System.Net.Sockets.SocketException:システムに十分なバッファスペースがないか、キューがいっぱいであるため、ソケットでの操作を実行できませんでした
私は次のようないくつかの役に立たないことを試しました:-MaxUserPortを最大値に設定し、レジストリで他のいくつかの推奨されるTCPIP設定。-異なるインターフェイス(実際のインターフェイスとループバック)で2つのサーバーを実行しようとし、複数のクライアントを使用します。
それはWindowsの既知の制限ですか、それとも何らかの方法でそれを克服する可能性がありますか?
助けてくれてありがとう!
c++ - IOCP と ReadFileEx の使用
私はIOCPで遊んでいます。メインスレッドでファイルから非同期にデータを読み取る単純なアプリケーションを作成しようとしています。ただし、ReadFileEx関数でエラー(ERROR_INVALID_PARAMETER)が発生していますが、問題なく実行しているようです。私は何を間違っていますか?これが私のサンプルです:
io - Win32 IO Completion Port と同期出現 IO はどうなりますか?
http://support.microsoft.com/kb/156932によると、特定の条件が満たされた場合、ReadFile の呼び出しは同期しているように見えます。たとえば、ターゲット ファイルが NTFS で圧縮されている場合です。この記事では、ファイル ハンドルが IOCP に関連付けられている場合に何が起こるかについては何も述べていません。
この場合、ファイル ハンドルが IOCP に関連付けられている場合はどうなるでしょうか。このリクエストの IO 完了パケットを引き続き受信しますか、それともリクエストは完全に同期して実行されますか?
その場合、ReadFile 呼び出し全体をワーカー スレッドに配置する必要があります。最初に ReadFile 呼び出しを発行するスレッドはブロックできません。IOCP を検討している理由は、ReadFile 呼び出しをワーカー スレッドに入れることは、ReadFile の直後にブロックするワーカー スレッドへのコンテキスト スイッチを意味するためです。
c# - BeginExecuteReader で IOCP が機能しない理由
BeginXX/EndXX ペアの呼び出しで IOCP が使用されているという記事をたくさん読みました。ただし、それらをテストしたところ、BeginExecuteReader 呼び出しでは IOCP が機能しなかったのに対し、BeginGetResponse 呼び出しでは問題なく機能したという結果が得られました。
私はこの結果に非常に混乱しています。誰でも理由を教えてもらえますか?私のテストコードに何か問題がありますか?
以下にテストを示します。
BeginGetResponse でテストする
コード:
結果:
コールバックの実行には 1 つの IO スレッドが使用されました。
BeginExecuteReader コードでテストします。
結果:
コールバックの実行に別の作業スレッドが使用されました
どうしたの?
c++ - IOCP を使用してクライアントの実際の IP アドレスとポートを取得するには?
サーバーでクライアントのIPアドレスとポートを取得する必要があります。サーバーは IOCP を使用して C++ で記述されているため、クライアントを受け入れません。新しいソケットを作成してから、この準備ができたソケットでクライアントを受け入れます (AcceptEx)。そのため、 struct sockaddr_in は正しくありません。
これどうやってするの?
ありがとう!
windows - 複数のコアにわたる Windows ネットワーク IOCP のスケーラビリティ
動作は次のとおりです。たとえば、200 個のソケットを持つ 1 つのサーバー ワーカーは、1 秒あたり 100K のエコーを処理します。同じポートで別のサーバー ワーカーを起動すると (各ワーカーのソケット数が同じか、2 倍少なくても問題ありません)、最初のワーカーのパフォーマンスがすぐに約 50% に低下し、マシンごとの全体的なパフォーマンスがわずかに向上します (各ワーカーがサービスを提供します)。 1 秒あたり約 50K のエコー)。
したがって、6 コア マシンのパフォーマンスは、1 コア マシンの場合とほぼ同じです。
各ワーカーに独立した IOCP ポートを 1 つ持つ (CreateIoCompletionPort で NumberOfConcurrentThreads を 1 に指定する)、すべてのワーカーに 1 つの共有 IOCP ポートを試す (NumberOfConcurrentThreads はワーカーの数に等しい) など、さまざまなアプローチを試しましたが、パフォーマンスは同じです。私のワーカーはデータを共有しないため、ロックなどはありません。
Windows カーネル ネットワークのスケーラビリティの問題ではなく、何かが欠けていることを願っています。Windows 7 Enterprise x64 を使用しています。
もちろん、パフォーマンスはほぼ直線的にスケーリングされることが期待されていました。
1 台のマシン上の複数のコアに対する IOCP の実用的なスケーラビリティについて知っている人はいますか? アクティブなソケットの数が増えると、どのような状況が予想されますか?
ありがとうございました!
c - IOCP: バイトコピーなしの通知
ソケット コンテキストごとに 64kb のバッファを格納する IOCP アプリケーションがあります。何千ものソケットを処理しながら、大量の RAM を使用します。これの代わりに、iocp-thread コンテキストごとに 64kb のバッファを持つモデルに切り替えたいと思います (epoll と kqueue でできるように)。このためには、提供された WSABUF にバイトをコピーすることなく通知を受信できる完了ポートが必要であり、通知の後、WSAEWOULDBLOCK を受信するまで非同期 WSARecvFrom (重複した構造を提供せずに、テストに udp を使用しています) を呼び出すだけです。構造が重複している WSARecvFrom 呼び出しに空の WSABUF (buf = NULL, len =0) を指定すると、次の手法を実現できることを読みました。しかし、うまくいきません: バッファーが小さすぎるため、IOCP が「起動」しません。
そのようなシナリオを可能にする他の方法はありますか?