2016-12-17 5 views
1

나는 clojure.async를 사용하여 소켓 읽기/쓰기를 추상화하는 몇 가지 기능을 작성하고 있습니다. 내 의도는 채널에 값을 써서 쓸 수 있고 읽을 채널에서 값을 팝핑 할 수 있다는 것입니다. 이 방법으로 사용자는 Reader s/Writer 초를 걱정할 필요가 없습니다.BufferedReader - 스트림 끝 부분의 블록

아래 코드는 루프의 소켓에서 읽은 내용을 채널로 전달합니다. 채널을 읽을 수 있도록 반환됩니다. 내 문제는 스트림의 끝에 도달하면 차단하는 대신 뭔가를 읽을 수있을 때까지 회전하는 것입니다. 이러한 프로세스가 몇 개 있으면 내 컴퓨터에서 눈에 띄는 성능 문제가 발생합니다.

이 문제를 해결하는 가장 쉬운 방법은 nil 대신에 BufferedReaderreadLine 블록이 EOF에있는 것입니다. 내가 볼 수있는 것으로부터 이것은 가능하지 않습니다. 대부분의 스트림에서 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

Rich Hickey 여러 번 이것이 좋은 생각이 아니며 그가 core.async에 대해 생각한 바가 아니라고 말했습니다. 그의 core.async 회담을보고이 배경에 대한 이론적 근거를 완전히 이해하고 싶을 수도 있습니다. 찾고있는 추상화를 구현하고 core.async와 통합 할 수있는 manifold 및 aleph와 같은 Zach Tellmans 라이브러리를 살펴보십시오. –

+0

@LeonGrapenthin에 말씀 하시려는 링크가 있습니까? 나는 그들을보고 싶다. :-) – jszakmeister

답변

0

여기서 유일하게 회전하는 것은 당신입니다. 스핀을 사용하는 클래스의 메소드는 없습니다. isConnectedisClosed 또는 isInputShutdown에 대한 설명서를 읽고 해결책이 명확 해집니다. 또한 readLine의 설명을 읽는 데 도움이되었으므로 더 이상 읽을 입력이 없을 때 반환되는 내용이 매우 명확합니다.

+0

나는이 대답이 무엇을 응답해야하는지 정말로 모른다. * getLine에 대한 문서를 읽었습니다. 주목할 부분은 "스트림의 끝에 도달하면 null을 반환합니다"부분입니다. 스트림의 끝을 나타내는 null이 반환되면'(valid-message? line)'은 false가되어 더 이상'>! '에 주차하지 않으므로 루프가 제어 할 수 없게됩니다. 빠른 루핑을 방지하는 방법을 알고 싶습니다. 그리고 나는 inConnected를 사용하는 실수를 저지르고 소켓이 연결되어 있지 않고 열려있는 동안에 만 루핑을 시도했으며 동작은 동일하게 유지되었습니다. – Carcigenicate

+0

이것은 답변의 링크이며, 가난하다는 것을 알고 있습니다. – Carcigenicate

+1

스트림의 끝을 읽을 때 스트림의 끝 부분에 있습니다. 들어오는 메시지가 절대로 없을 것입니다. 그것이 바로 스트림의 끝이 의미하는 것입니다. 그것은 "지금 아무것도 없다"는 것을 의미하지는 않습니다. – amalloy

0

이후에도 읽어야 할 것이 더 있는지 여부를 확인할 수있는 방법이 java.io.BufferedReader.ready()입니다. 또한 Sockets은 을 사용하여 BufferedReader으로 강제 변환 될 수 있습니다. 작가에게도 마찬가지입니다.

나는 core.async에 익숙하지 않아 도움이되는지 전혀 모른다.