写着玩的,不使用任何网络框架从头构建的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 }))
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