Sockets 如何捕捉SocketException
我在使用以下F#Sockets 如何捕捉SocketException,sockets,f#,try-with,Sockets,F#,Try With,我在使用以下F#try..with语句的部分构造时遇到问题。有很多异常处理示例,但我找不到任何与主机不存在时从Dns.GetHostEntry返回的SocketException特别匹配的异常。我将继续寻找,但如果能给我一个指针,我将不胜感激 let test_smtp (smtp_server_address : string) (port : int) = let expectedResultCode = 220 let hostEntry : IPHostEntry =
try..with
语句的部分构造时遇到问题。有很多异常处理示例,但我找不到任何与主机不存在时从Dns.GetHostEntry
返回的SocketException
特别匹配的异常。我将继续寻找,但如果能给我一个指针,我将不胜感激
let test_smtp (smtp_server_address : string) (port : int) =
let expectedResultCode = 220
let hostEntry : IPHostEntry =
try
Dns.GetHostEntry(smtp_server_address)
with
| :? System.Net.Sockets.SocketException -> printfn "GetHostEntry threw an exception "
let endPoint : IPEndPoint = new IPEndPoint (hostEntry.AddressList.[0], port)
( use tcpSocket = new Socket(endPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp)
tcpSocket.Connect(endPoint)
let temp_result = check_response tcpSocket expectedResultCode
temp_result
)
到目前为止,你所拥有的一切都很好;您只需要添加as(name)
语法来为异常对象命名,然后添加when(test)
语法来测试某个条件是否成立。例如:
try
Dns.GetHostEntry(smtp_server_address)
with
| :? System.Net.Sockets.SocketException as ex when ex.SocketErrorCode = SocketError.HostNotFound ->
failwith "Host not found"
(注意:我的原始代码是针对int测试的SocketErrorCode
,因为我误读了MSDN文档。但它是一个。)
关于代码的一点意见是:在use tcpSocket=…
表达式周围不需要那些括号。您只需将其与代码的其余部分内联编写,当函数末尾的tcpSocket
值超出范围时,F#将处理该值:
let test_smtp (smtp_server_address : string) (port : int) =
let expectedResultCode = 220
let hostEntry : IPHostEntry =
try
Dns.GetHostEntry(smtp_server_address)
with
| :? System.Net.Sockets.SocketException as ex when ex.SocketErrorCode = SocketError.HostNotFound ->
failwith "GetHostEntry threw an exception "
let endPoint : IPEndPoint = new IPEndPoint (hostEntry.AddressList.[0], port)
use tcpSocket = new Socket(endPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp)
tcpSocket.Connect(endPoint)
check_response tcpSocket expectedResultCode
以下不是解决方案,而是一种变通方法。它绕过了主机未找到错误的问题,而不必使用@rmunn的答案中提到的方法。(顺便说一句,这是一篇很棒的文章。)
因此,如果Dns.GetHostEntry
引发异常,或者check\u response
未能从HELO
获得正确响应,则可以返回false
module net_utilF_mod
open System
open System.Text
open System.Threading
open System.Net
open System.Net.Sockets
open System.IO
type Smtp1() =
member this.X = "F#"
let send_data (socket : Socket) (data : string) =
let dataArray : byte [] = Encoding.ASCII.GetBytes(data)
socket.Send(dataArray, 0, dataArray.Length, SocketFlags.None)
let check_response (socket:Socket) expectedResultCode =
while socket.Available = 0 do
System.Threading.Thread.Sleep 100
let responseArray : byte [] = Array.zeroCreate 1024
socket.Receive(responseArray, 0, socket.Available, SocketFlags.None) |> ignore
let responseData : string = Encoding.ASCII.GetString(responseArray)
let responseCode : int = Convert.ToInt32(responseData.Substring(0,3))
if responseCode = expectedResultCode then
true
else
false
let test_smtp (smtp_server_address : string) (port : int) =
let helo_msg = String.Format("HELO {0}\r\n", Dns.GetHostName())
let hostEntry : IPHostEntry =
try
Dns.GetHostEntry(smtp_server_address)
with
| :? System.Net.Sockets.SocketException as ex when ex.SocketErrorCode = SocketError.HostNotFound ->
let tempEntry : IPHostEntry = Dns.GetHostEntry(@"localhost")
tempEntry
let email_server_reachable =
match hostEntry.HostName with
| @"localhost" -> false
| _ -> true
if false = email_server_reachable then
false
else
let endPoint : IPEndPoint = new IPEndPoint (hostEntry.AddressList.[0], port)
( use tcpSocket = new Socket(endPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp)
tcpSocket.Connect(endPoint) |> ignore
let temp_response =
if true = check_response tcpSocket 220 then
send_data tcpSocket helo_msg |> ignore
check_response tcpSocket 250
else
false
temp_response
)
修复后,出现了第二个错误。它抱怨大约11001以及最初的错误,说它应该是一个IPHostEntry。@octopusgrabbus-我最初的答案是错误的:SocketErrorCode
是一个枚举。我已经更新了。让我看看iPhonestry的事。。。。而且printfn
是错误的printfn
返回()
,即单元类型。但是try…with
表达式的每个分支都需要返回与Dns.GetHostEntry
相同的类型,或者抛出异常。所以我更新了我的示例以抛出一个异常,因为没有可以返回的有意义的IPHostEntry
。除非你重写这个函数来使用样式,但这是一个更大的问题。你是对的。剩下的只是抱怨我们分配给了iPhonentry,但改为了“a*b”。我不得不重新编写它,因为我想让程序继续。一个简短的风格评论:我发现if true=(布尔值)
比简单的if(布尔值)
可读性差得多。同样地,if false=(布尔值)
的可读性低于if not(布尔值)
。这是许多Javascript程序员的习惯,因为Javascript的非严格类型,但在F#中没有必要,因为F#具有严格的类型,所以您可以使用可读性更高的if(boolean)
。您的match
表达式设置了email\u server\u reachable
的可读性,因为让email\u server\u reachable=hostEntry.HostName“localhost”
。一行,易于阅读。