套接字连接的惯用异常处理
Posted
技术标签:
【中文标题】套接字连接的惯用异常处理【英文标题】:Idiomatic exception handling for socket connection 【发布时间】:2015-05-25 23:24:02 【问题描述】:我正在尝试了解如何优雅地使用 scala.util.control.Exception
包。
更具体地说,我想将这段 Java 代码转换为函数式:
public static boolean hostAvailabilityCheck()
try (Socket s = new Socket(SERVER_ADDRESS, TCP_SERVER_PORT))
return true;
catch (IOException ex)
/* ignore */
return false;
我可以在 Scala 中使用 try-catch-finally 做同样的事情,但我正在寻找更实用的方法。另请注意,此 Java 代码使用try-with-resources
,因此这意味着此代码无论如何都会关闭套接字(即使发生异常):socket.close()
【问题讨论】:
【参考方案1】:---在问题澄清后编辑---
要在 scala 中以函数式风格使用自动资源管理,最简单的方法是使用 scala-arm 然后您可以编写
import resource._
def hostAvailabilityCheck():Boolean=
managed(new Socket(SERVER_ADDRESS, TCP_SERVER_PORT)).map(_=>true).opt.isDefined
如果你真的,真的想使用scala.util.control.Exception
,你可以写:
import scala.util.control.Exception._
def hostAvailabilityCheck():Boolean=
catching[IOException].opt(new Socket(SERVER_ADDRESS, TCP_SERVER_PORT)). isDefined
return false;
更好的是,您可以使用Try
类型来执行此操作,在这种情况下,您的原始方法将变为:
def hostAvailabilityCheck():Boolean =
Try(new Socket(SERVER_ADDRESS, TCP_SERVER_PORT)).isSuccess
从您的示例中不清楚您想对此做什么,但返回 Try
而不是布尔值可能很有用,这样如果端口获取成功,您就不必等待在以更明确的方式重新绑定之前,在操作系统级别进行端口回收。
def hostAvailabilityCheck(port: Int):Try[Socket] =
Try(new Socket(SERVER_ADDRESS, port))
然后你的客户端代码可能会尝试获取一个端口,直到它真正得到一个:
def acquire(port: Int):Socket=
hostAvailabilityCheck(port).recoverWith(case t:Throwable => acquire(port)).get
这是一个幼稚的实现,因为它会触发一个无限循环,等待端口可用,并可能尝试捕获不可恢复的错误,但它应该给你一个大致的想法。 只有当您使用 0 作为端口值时,该实现才会真正有用,在这种情况下,它将尝试各种随机端口,直到找到一个空闲的端口。
【讨论】:
非常感谢您的回答。使用Try
的选项在我看来更优雅,但它的问题是Java 代码会自动关闭新的Socket(因为它使用try-with-resources 块)。这是我的主要问题,即如何优雅地将其转换为功能样式并正确关闭资源。
你能在问题中澄清一下,我将添加一个部分
看起来很有希望,再次感谢,但我仍然有 1 个错误:未为我定义托管资源的 opt
方法。如果 scala-arm - 1.4,我正在使用最新版本
确实,出于某种原因,您必须先映射,然后才能提取。我的示例代码中留下了一张地图,我在粘贴答案时对其进行了编辑:)
我不知道 Scala-arm,谢谢。 AFAIK:“传统的”Scala 方式是using
。我个人更喜欢(标准)Try
monad,但在这种情况下它会关闭Socket
吗?另外,Scala-arm 是如何知道何时以 monadic 样式关闭资源的?以上是关于套接字连接的惯用异常处理的主要内容,如果未能解决你的问题,请参考以下文章
Python开发基础----异常处理socket套接字基础1
Python开发基础-Day23try异常处理socket套接字基础1