0

私のアプリは、プロシージャへの呼び出しでハングしていますTIdStackWindows.Connect。TCP/IP アドレスが存在する場合は問題ありませんが、存在しない場合はハングします。IP アドレスはリテラルです。DNS ルックアップは必要ありません。タイムアウト後に接続試行が失敗することを期待していました ( TCPClient.ConnectTimeout) 1 秒に設定しましたが、この呼び出しでアプリが最大 30 秒間ハングします (アプリからの呼び出しはスレッド化されていません。TCP 接続をスレッドですが、長い接続タイムアウトは依然として問題になります)。

アプリが応答しないときに Delphi IDE で実行を一時停止すると、次の場所に配置されます。

ntdll.KiUserApcDispatcher:
7C90E450 8D7C2410         lea edi,[esp+$10]

次に、スタック フレームが表示されるまで F8 キーを数回押します。私はその時:

IdStack.TIdStack.RaiseSocketError(10038)
IdStack.TIdStack.RaiseLastSocketError
IdStack.TIdStack.CheckForSocketError(-1)
IdStackWindows.TIdStackWindows.Connect(912,'10.8.2.170',5001,Id_IPv4)
IdSocketHandle.TIdSocketHandle.Connect
IdIOHandlerStack.TIdConnectThread.Execute
:00451fc1 HookedTThreadExecute + $2D
Classes.ThreadProc($254B910)
System.ThreadWrapper($5456CB0)
:00451ea3 CallThreadProcSafe + $F
:00451f10 ThreadExceptFrame + $3C
:7c80b729 ; C:\WINDOWS\system32\kernel32.dll

少し調べてみたところ、このトピックに少しトラフィックがあったことに気付きました。一般的な答えは「スレッドに入れる」ようです。私はそうするつもりですが、長いタイムアウトは依然として問題になります。接続タイムアウトが機能しないのはなぜですか? Indy 10.5.5 と Delphi 2006 を使用しています。Indy の最新ビルドにアップグレードすると、多くの移行が必要になりますか?

4

1 に答える 1

4

ブロッキング ソケットには API レイヤーでの接続タイムアウトの概念がないため、IndyConnectTimeoutは手動で実装されたタイムアウトです。Indy は、そのスレッドが終了するのを待機するスリープ ループを実行しているTIdStack.Connect()間に、内部ワーカー スレッドを呼び出します。TIdTCPClient.Connect()ループがConnectTimeout期間の経過を検出すると、ソケットを閉じます。これにより、ブロックされTIdStack.Connect()たものがすぐに終了するはずですが、それは保証されません。スレッドの作成と終了にも OS のオーバーヘッドがあります。1 秒のタイムアウトに反応するのに 30 秒もかからないはずですが、通常、1 秒では短すぎます。スレッドが 1 秒以内に実行を開始しない可能性もあります。OS が作業を行うのに十分な時間を与えるために、通常ConnectTimeoutは最低でも 5 ~ 10 秒に設定する必要があります。

于 2011-10-31T05:18:24.607 に答える