zl程序教程

您现在的位置是:首页 >  其他

当前栏目

A 77 lines echo server in clojure

2023-03-14 22:28:50 时间
  写着玩的,不使用任何网络框架从头构建的echo server,总共77行。
 1 ;;Author:dennis (killme2008@gmail.com)
 2 (ns webee.network
 3    (:import (java.nio.channels Selector SocketChannel ServerSocketChannel SelectionKey)
 4             (java.net InetSocketAddress)
 5             (java.nio ByteBuffer)
 6             (java.io IOException)))
 7 
 8 (declare reactor process-keys accept-channel read-channel)
 9 
10 (defn bind [^InetSocketAddress addr fcol]
11   (let [selector (Selector/open)
12         ssc      (ServerSocketChannel/open)
13         ag  (agent selector)]
14     (do
15       (.configureBlocking ssc false)
16       (.. ssc (socket) (bind addr 1000))
17       (.register ssc selector SelectionKey/OP_ACCEPT)
18       (send-off ag reactor fcol)
19       ag)))
20 
21 (defn- reactor [^Selector selector fcol]
22   (let [sel (. selector select 1000)]
23     (if (> sel 0)
24       (let [sks (. selector selectedKeys)]
25         (do 
26           (dorun (map (partial process-keys selector fcol) sks))
27           (.clear sks))))
28     (recur selector fcol)))
29   
30 (defn- process-keys [^Selector selector ^SelectionKey fcol sk]
31   (try
32     (cond 
33       (.isAcceptable sk) (accept-channel sk  selector fcol)
34       (.isReadable sk) (read-channel sk selector fcol)    
35     )
36     (catch Throwable e (.printStackTrace e))))
37 
38 (defn- accept-channel [^SelectionKey sk ^Selector selector fcol]
39    (let [^ServerSocketChannel ssc (. sk channel)
40          ^SocketChannel sc (. ssc accept)
41          created-fn (:created fcol)]
42      (do 
43        (.configureBlocking sc false
44        (.register sc selector SelectionKey/OP_READ)
45        (if created-fn
46          (created-fn sc)))))
47 
48 (defn- close-channel [^SelectionKey sk ^SocketChannel sc fcol]
49   (let [closed-fn (:closed fcol)]
50     (do 
51        (.close sc)
52        (.cancel sk)
53        (if closed-fn 
54          (closed-fn sc)))))
55      
56 (defn-  read-channel [^SelectionKey sk ^Selector selector fcol]
57    (let [^SocketChannel sc (. sk channel)
58          ^ByteBuffer buf (ByteBuffer/allocate 4096)
59          read-fn (:read fcol)]
60      (try
61        (let [n (.read sc buf)]
62          (if (< n 0)
63              (close-channel sk sc fcol)
64              (do (.flip buf)
65                  (if read-fn
66                    (read-fn sc buf)))))
67        (catch IOException e
68          (close-channel sk sc fcol)))))
69 
70 ;;Bind a tcp server to localhost at port 8080,you can telnet it.
71 (def server
72   (bind 
73     (new InetSocketAddress 8080)
74     {:read #(.write %1 %2)
75      :created #(println "Accepted from" (.. % (socket) (getRemoteSocketAddress)))
76      :closed  #(println "Disconnected from" (.. % (socket) (getRemoteSocketAddress)))
77      }))
文章转自庄周梦蝶  ,原文发布时间 2011-01-15