套接字连接的惯用异常处理

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 中收集和报告多个异常的惯用方式

Python开发基础----异常处理socket套接字基础1

Python开发基础-Day23try异常处理socket套接字基础1

python基础之try异常处理socket套接字基础part1

Clojure 中的惯用错误处理

.NET 远程处理目标拒绝单个调用 - 返回套接字异常