A 77 lines echo server in clojure
luyued 发布于 2011-01-26 11:52 浏览 N 次
写着玩的,不使用任何网络框架从头构建的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 }))
dennis 2011-01-15 22:56 发表评论
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 }))
dennis 2011-01-15 22:56 发表评论
相关资讯
- 07-01· 古珀行钻戒 钻石情缘
- 07-01· 庆祝古珀行珠宝乌审旗珠
- 07-01· 加盟戴梦得古珀行成就财
- 07-01· 戴梦得古珀行代表了传统
- 07-01· 527=我爱妻 爱妻就为她做点
- 07-01· 中国时尚街拍网时尚街拍
- 07-01· 财富中国名媛学堂
- 07-01· 哥特式名媛打广告:关于叛
- 07-01· 名媛最爱 2011春季新款高跟
- 07-01· 足浴店开业宣传单为你免
图文资讯
最新资讯
- 07-01· SEM深入探究-两岸职工小发
- 07-01· 柳坪中小学主要领导
- 07-01· 移植名古树和人生历炼成
- 07-01· 亿赛通苦练内功,现身“
- 07-01· 阿美,别哭
- 07-01· [有声小说 www.51ysxs.com]“把
- 07-01· 2009年 大学生就业创业论坛
- 07-01· 创意生活点亮“个性家居
- 07-01· 各界名流齐聚2010中国新丝
- 07-01· 2011世界财富小姐英才大赛