写着玩的,不使用任何网络框架从头构建的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
转载请注明原文地址: https://yun.8miu.com/read-115360.html