当社のアプリケーションには、顧客の社内工場ネットワークに積極的に接続し、検査イベントが発生したときにメッセージを送信する機能があります。顧客は、自分のマシンとアプリケーションのIPアドレスとポート番号を当社のソフトウェアに入力します。Windowsソケットエラーの解決WSAENOBUFS(10055)
私はブロックモードでTClientSocketを使用しており、OnConnect
とOnError
イベントに対してコールバック関数を提供しています。アプリケーションの起動時には、私は別のスレッドで、次のコードを呼び出すときに、上記の機能を仮定すると、活性化されている:
// Attempt active connection
try
m_socketClient.Active := True;
except
end;
// Later...
// If `OnConnect` and socket is connected...send some data!
// If `OnError`...call `m_socketClient.Active := True;` again
IP +ポートが有効な場合は、機能がうまく動作します。しかし、そうでない場合、最終的にWindowsソケットエラー10055(WSAENOBUFS)が発生し、アプリケーションがクラッシュし、数千のエラー(および数時間または数日後)が発生します。このようthis one from ServerFrameworkとthis one from Microsoft話として
様々な記事を約exhausting the Windows non-paged pool
と言及(1)積極的に未処理の非同期操作を送信数を管理し、(2)I/O操作に使用されたデータ・バッファを解放します。
私の質問はこれを実現する方法ですと3倍です:
A)私はメモリがリークされていることを何か間違ったことをやっていますか?たとえば、OnError
ハンドラにクリーンアップコードがありませんか?
B)I/Oバッファが枯渇しているかどうかを監視するにはどうすればよいですか?私はProcess Explorer
を使用してアプリケーションがリークの原因であることを確認しましたが、理想的にはこれをプログラム的に測定する方法が必要です。
C)アプリケーションを再起動する以外に、I/O操作データバッファをクリアまたは解放するようWindowsに依頼する方法はありますか?
Delphi、C/C++、C#fineのコードサンプル。
おそらく、 'TClientSocket'はDelphi 6以降では廃止されていますが、今は16年半前です。これらのコンポーネントが適切にハンドルをクリーンアップしない場合、私は驚くことはありません。 (シェルコンポーネントのように)あまり書かれていなかった他のDelphiコンポーネントも廃止され、後で削除されました。 –
ありがとうございましたGünther、実際に私はそれを知らなかった。私が使用するコンポーネントをリフレッシュする必要があります!調査とテストの日の後、私は問題(これらのTCP/IPコンポーネントの使用経験がないことを反映しています)を発見したと思います。ソケットがタイムアウトしてOnErrorイベントを起動すると、 'm_socketClient.Socket.Close()'を呼び出します。私の調査を完了するのに忙しくて、それに基づいて答えを打ち明けます。 – AlainD
'TClientSocket'は廃止されるかもしれませんが、かなり堅実なコンポーネントです。私はこれまでメモリ/リソースに関する問題は一度も経験しておらず、私はこれを非常に長い間使ってきました。しかし、OnErrorイベントで 'Active:= True'を設定しようとしたことはありません。そのイベントで失敗したソケットを常に 'Close()'してから、スレッドがソケットを再び開くタイミングを決定させます。接続を開くときにエラーが発生した場合は、接続をもう一度開こうとする前に、数秒待つことをお勧めします。 I/Oの読み込み/書き込み中にエラーが発生した場合は、直ちに再接続してください。 –