Here's the resulting source code from my experimentation.
(import '(java.net BindException ServerSocket Socket) '(java.lang.reflect InvocationTargetException) '(java.util Date) '(java.io InputStream OutputStream) '(java.util.concurrent Executors)) ;;; Utility functions (defn current-time [] (. (new Date) (toString))) (defn byte-arr-from-string [str] (. str (getBytes))) (defn test-byte-array-from-string ([] (test-byte-array-from-string (current-time))) ([str] (let [barr (byte-arr-from-string str) bseq (map (comp char (appl aget barr)) (range (alength barr))) chseq (map char str)] (and (== (alength barr) (count bseq) (count chseq)) (nil? (first (filter false? (map eql? bseq chseq)))))))) (defn string-from-byte-sequence [coll] (reduce strcat (map char coll))) ;;; Listener functions ;;; These control the server (defn listener-new [port] (try (new ServerSocket port) (catch BindException except (println "Address is already in use.")))) (defn listener-wait [listener] (. listener (accept))) (defn listener-close [listener] (. listener (close))) (defn listener-send [lsocket] (.. lsocket (getOutputStream) (write (byte-arr-from-string (current-time)))) (.. lsocket (getOutputStream) (close)) lsocket) (defn listener-run [listener port] (loop [socket nil] (if (. listener (isClosed)) listener (do (when socket (. (listener-send socket) (close))) (recur (listener-wait listener)))))) (defn listener-run-in-background [port] (let [listener (listener-new port) exec (. Executors (newSingleThreadExecutor)) run (appl listener-run listener port)] (when listener (. exec (submit run))) listener)) ;;; Connection functions ;;; These control the client. (defn connection-new ([port] (connection-new "127.0.0.1" port)) ([address port] (try (doto (new Socket address port) (setSoTimeout 5000)) (catch InvocationTargetException except (println (strcat "Could not connect to " address " on port " port)))))) (defn connection-read [conn] (let [instream (. conn (getInputStream)) reader (fn [] (try (. instream (read)) (catch InvocationTargetException except -1)))] (loop [bytes nil current-byte (reader)] (if (== current-byte -1) bytes (recur (concat bytes (list current-byte)) (reader)))))) (defn connection-close [conn] (. conn (close))) (defn connection-run [port] (let [conn (connection-new port) str (when conn (string-from-byte-sequence (connection-read conn)))] (when conn (connection-close conn)) str))
0 comments:
Post a Comment