あなたのテストを再現する-それは私のために働く
あなたは誰かが同じ問題に遭遇したかどうか尋ねました-私はちょうどあなたのコードをWindows7、VS2008で.NET2.0で試しました-それはうまくいきました。タイムアウトをに設定すると1
、ご存知のとおり、このエラーがすぐに発生します。
Unhandled Exception: System.Net.Mail.SmtpException: The operation has timed out
at System.Net.Mail.SmtpClient.Send(MailMessage message)
at mailtimeout.Program.Main(String[] args) in c:\test\mailtimeout\Program.cs:line 29
問題は、タイムアウトとは異なる何かを期待していることかもしれないと思います。タイムアウトとは、接続が正常に確立されたが、サーバーから応答が返されなかったことを意味します。これは、宛先のポート25で実際にサーバーがリッスンしている必要があることを意味しますが、サーバーは応答しません。このテストでは、Tclを使用して、何もしなかった25のソケットを作成します。
c:\> tclsh
% socket -server foo 25
タイミングをに変更したとき、15000
5秒後にタイムアウトエラーが発生しませんでした。
接続できない場合にSmtp.Timeoutが効果を発揮しない理由
system.net.tcpclient
ポート25で何もリッスンしていない場合、またはホストに到達できない場合、タイムアウトは、レイヤーがタイムアウトする少なくとも20秒まで発生しません。これはsystem.net.mail
レイヤーの下にあります。問題と解決策を説明する優れた記事から:
System.Net.Sockets.TcpClientとSystem.Net.Sockets.Socketの2つのクラスのどちらにも、ソケットを接続するためのタイムアウトがないことに気付くでしょう。私はあなたが設定できるタイムアウトを意味します。.NETソケットは、同期/非同期ソケット接続の確立中にConnect / BeginConnectメソッドを呼び出すときに、接続タイムアウトを提供しません。代わりに、接続しようとしたサーバーがリッスンしていない場合、またはネットワークエラーが発生した場合、接続は非常に長い時間待機してから例外がスローされます。デフォルトのタイムアウトは20〜30秒です。
メールからそのタイムアウトを変更する機能はありません(これは理にかなっています、メールサーバーは通常稼働しています)。実際、接続をから変更する機能はありませんsystem.net.socket
。これは本当に驚くべきことです。ただし、非同期接続を実行すると、ホストが起動していてポートが開いているかどうかを確認できます。このMSDNスレッド、特にこの投稿から、このコードは機能します。
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IAsyncResult result = socket.BeginConnect("192.168.1.180", 25, null, null);
// Two second timeout
bool success = result.AsyncWaitHandle.WaitOne(2000, true);
if (!success) {
socket.Close();
throw new ApplicationException("Failed to connect server.");
}