我正在编写一些使用clojure.async的函数来抽象读取/写入套接字。我的意图是可以将值放入通道以便编写它们,并从要读取的通道弹出。这样,用户无需担心Reader
s / Writer
s。
下面的代码从循环中的套接字读取,将其读取的任何内容转发到通道中。返回通道以便可以读取它。我的问题是,当到达流的末尾而不是阻塞时,它会在那里旋转直到可以读取某些内容。如果我有一些这样的过程,它会在我的计算机上产生明显的性能问题。
我能看到解决此问题的最简单方法是以某种方式阻止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))
答案 0 :(得分:1)
这里唯一旋转的是你。您正在使用的类中没有旋转方法。阅读isConnected和isClosed或isInputShutdown的文档,解决方案应该变得清晰。它也可以帮助你阅读readLine的描述,当没有更多的输入要读时,它的内容非常清楚。
答案 1 :(得分:0)
即使在java.io.BufferedReader.ready()
之后,EOF
方法也可以检查是否还有其他内容需要阅读。此外,Sockets
只需使用BufferedReader
即可强制转换为(clojure.java.io/reader socket)
。作家也一样。
我对core.async
不太熟悉,所以不知道这是否有帮助。