BufferedReader - 流结束时阻塞

时间:2016-12-17 20:48:18

标签: sockets clojure bufferedreader channel

我正在编写一些使用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))

2 个答案:

答案 0 :(得分:1)

这里唯一旋转的是你。您正在使用的类中没有旋转方法。阅读isConnectedisClosedisInputShutdown的文档,解决方案应该变得清晰。它也可以帮助你阅读readLine的描述,当没有更多的输入要读时,它的内容非常清楚。

答案 1 :(得分:0)

即使在java.io.BufferedReader.ready()之后,EOF方法也可以检查是否还有其他内容需要阅读。此外,Sockets只需使用BufferedReader即可强制转换为(clojure.java.io/reader socket)。作家也一样。

我对core.async不太熟悉,所以不知道这是否有帮助。