A 77 lines echo server in clojure

    写着玩的,不使用任何网络框架从头构建的echo server,总共77行。
 1  ;;Author:dennis ([email protected])
 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       }))


你可能感兴趣的:(A 77 lines echo server in clojure)