【发布时间】:2017-05-03 08:12:57
【问题描述】:
我正在编写一些函数,这些函数使用 clojure.async 来抽象出对套接字的读/写。我的意图是可以将值放入通道中以进行写入,并从通道中弹出以进行读取。这样用户就不用担心Readers/Writers了。
下面的代码在循环中从套接字读取,将它读取的任何内容转发到通道中。通道被返回,因此可以从中读取。我的问题是,当到达流的末尾时,它不是阻塞,而是坐在那里旋转,直到可以读取某些内容。如果我有一些这样的进程正在运行,它会在我的计算机上产生明显的性能问题。
我可以看到解决此问题的最简单方法是以某种方式在 EOF 上设置 BufferedReader 的 readLine 块,而不是返回 nil。不过,据我所知,这是不可能的。但这并不让我感到惊讶,因为大多数流的 EOF 阻塞会很奇怪。但是对于套接字流,EOF 似乎没有特定的含义,因为即使到达 EOF 仍然可以接收消息。
一旦到达 EOF,有没有办法防止循环在等待输入时旋转?
(ns chat.so-example
(:require [clojure.core.async :as a :refer [chan go >!]])
(:import [java.net Socket SocketException]
[java.io BufferedReader InputStreamReader InputStream]))
(defn valid-message? [msg]
(and (some? msg)
(not (empty? msg))))
(defn new-input-chan [^Socket sock]
(let [^InputStream in (.getInputStream sock)
buff-reader (BufferedReader. (InputStreamReader. in))
in-chan (chan)]
(go
(try
(while (.isConnected sock) ; This spins when EOF is reached
(let [line (.readLine buff-reader)]
(when (valid-message? line)
(>! in-chan line))))
(catch SocketException se
(#_"Handle exception"))
(finally
(a/close! in-chan))))
in-chan))
【问题讨论】:
-
Rich Hickey 多次表示这不是一个好主意,也不是他对 core.async 的想法。您可能想观看他的 core.async 演讲,以充分了解其背后的基本原理。看看 Zach Tellmans 库,如 manifest 和 aleph,它们实现了您正在寻找的抽象并与 core.async 集成。
-
@LeonGrapenthin 你有上述会谈的链接吗?我想看他们。 :-)
标签: sockets clojure bufferedreader channel