1 非阻塞(Nonblocking)体系结构
在这一部分,我将从理论的角度来解释非阻塞体系的结构及其工作原理。这部“喜剧”(当然,如果你喜欢的话也可以称做戏剧)的“人物”如下:
●服务器端:接收请求的应用程序。
●客户端:向服务器端发出请求的应用程序。
●套接字通道:客户端与服务器端之间的通信通道。它能识别服务器端的IP地址和端口号。数据以Buffer中元素的形式通过套接字通道传送。
●选择器:所有非阻塞技术的主要对象。它监视着已注册的套接字通道,并序列化服务器需要应答的请求。
●关键字:选择器用来对对象的请求进行排序。每个关键字代表一个单独的客户端子请求并包含识别客户端和请求类型的信息。
2 SocketChannel 类
SocketAddress rama = new SocketAddress("localhost" , 8888) ;
利用静态工厂方法得到SocketChannel的实例。
SocketChannel client = SocketChannel.open(rama) ;
如果这是传统的套接字,那么就会寻求得到socket的输入或者输出流,利用通道,我们可以直接写入通道本身,
不是写入字节数组,而是要写入ByteBuffer对象,将此对象写入 client的read 方法。

客户端应用程序同时执行对服务器端的请求,接着选择器将其集中起来,创建关键字,然后将其发
送至服务器端。这看起来像是阻塞(Blocking)体系,因为在一定时间内只处理一个请求,但事实并非如此。
实际上,每个关键字不代表从客户端发至服务器端的整个信息流,仅仅只是一部分。我们不要忘了选择器能
分割那些被关键字标识的子请求里的数据。因此,如果有更多连续地数据发送至服务器端,那么选择器就会
创建更多的根据时间共享策略(Time-sharing policy)来进行处理的关键字。强调一下,在图一中关键字的颜色
与客户端的颜色相对应。
服务器端非阻塞(Server Nonblocking)
客户端和服务器端是两个Java应用程序。套接字通道是SocketChannel类的实例,这个类允许通过网络传送数据。
它们能被Java程序员看作是一个新的套接字。SocketChannel类被定义在java.nio.channel包中。
选择器是一个Selector类的对象。该类的每个实例均能监视更多的套接字通道,进而建立更多的连接。
当一些有意义的事发生在通道上(如客户端试图连接服务器端或进行读/写操作),选择器便会通知应用程序处理请求。
选择器会创建一个关键字,这个关键字是SelectionKey类的一个实例。每个关键字都保存着应用程序的标识及请求的类型。
其中,请求的类型可以是如下之一:
基本上,服务器端的实现是由选择器等待事件和创建关键字的无限循环组成的。根据关键字的类型,及时的执行操作。
关键字存在以下4种可能的类型。
Acceptable: 相应的客户端要求连接。
Connectable:服务器端接受连接。
Readable:服务器端可读。
Writeable:服务器端可写。
一个通用的实现非阻塞服务器的算法如下:
create SocketChannel;
create Selector
associate the SocketChannel to the Selector
for(;;) {
waiting events from the Selector;
event arrived; create keys;
for each key created by Selector {
check the type of request;
isAcceptable:
get the client SocketChannel;
associate that SocketChannel to the Selector;
record it for read/write operations
continue;
isReadable:
get the client SocketChannel;
read from the socket;
continue;
isWriteable:
get the client SocketChannel;
write on the socket;
continue;
}
}
3 下面为一个实例
(1)客户端
1
 packagecn.bupt.channel;2
packagecn.bupt.channel;2 3
3 importjava.io.IOException;4
importjava.io.IOException;4 importjava.net.InetSocketAddress;5
importjava.net.InetSocketAddress;5 importjava.net.SocketAddress;6
importjava.net.SocketAddress;6 importjava.nio.ByteBuffer;7
importjava.nio.ByteBuffer;7 importjava.nio.channels.Channels;8
importjava.nio.channels.Channels;8 importjava.nio.channels.SocketChannel;9
importjava.nio.channels.SocketChannel;9 importjava.nio.channels.WritableByteChannel;10
importjava.nio.channels.WritableByteChannel;10 11
11 importcn.bupt.constant.Default;12
importcn.bupt.constant.Default;12 13
13
 publicclassChargenClient
publicclassChargenClient {14
{14 15
15 publicstaticintDEFAULT_PORT=8778;16
publicstaticintDEFAULT_PORT=8778;16
 /** *//**17
/** *//**17 *@paramargs18
     *@paramargs18 */19
*/19
 publicstaticvoidmain(String[] args)
publicstaticvoidmain(String[] args) {20
{20 //TODO Auto-generated method stub21
//TODO Auto-generated method stub21 if(args.length==0)22
if(args.length==0)22

 {23
{23 System.out.println("please input the port");24
           System.out.println("please input the port");24 return;25
return;25 }26
       }26 27
27 intport ;28
intport ;28 29
29 30
30 port=DEFAULT_PORT ;31
       port=DEFAULT_PORT ;31 32
32 SocketAddress address=newInetSocketAddress(args[0] , port) ;33
       SocketAddress address=newInetSocketAddress(args[0] , port) ;33
 try
try {34
{34 SocketChannel client=SocketChannel.open(address) ;35
        SocketChannel client=SocketChannel.open(address) ;35 ByteBuffer buffer=ByteBuffer.allocate(74) ;36
        ByteBuffer buffer=ByteBuffer.allocate(74) ;36 WritableByteChannel out=Channels.newChannel(System.out) ;37
        WritableByteChannel out=Channels.newChannel(System.out) ;37 38
38 while(client.read(buffer)!=-1)39
while(client.read(buffer)!=-1)39

 {40
{40 buffer.flip() ;41
            buffer.flip() ;41 out.write(buffer) ;42
            out.write(buffer) ;42 buffer.clear() ;43
            buffer.clear() ;43 44
44 }45
        }45 46
46 47
47 48
48 49
49 50
50 51
51
 }catch(IOException e)
    }catch(IOException e) {52
{52 //TODO Auto-generated catch block53
//TODO Auto-generated catch block53 e.printStackTrace();54
e.printStackTrace();54 }55
    }55 56
56 57
57 58
58 }59
    }59 60
60 }61
}61
(2) 服务器端
1
 packagecn.bupt.channel;2
packagecn.bupt.channel;2 3
3 importjava.io.IOException;4
importjava.io.IOException;4 importjava.net.InetSocketAddress;5
importjava.net.InetSocketAddress;5 importjava.net.ServerSocket;6
importjava.net.ServerSocket;6 importjava.nio.ByteBuffer;7
importjava.nio.ByteBuffer;7 importjava.nio.channels.SelectionKey;8
importjava.nio.channels.SelectionKey;8 importjava.nio.channels.Selector;9
importjava.nio.channels.Selector;9 importjava.nio.channels.ServerSocketChannel;10
importjava.nio.channels.ServerSocketChannel;10 importjava.nio.channels.SocketChannel;11
importjava.nio.channels.SocketChannel;11 importjava.util.Iterator;12
importjava.util.Iterator;12 importjava.util.Set;13
importjava.util.Set;13 14
14
 publicclassChargenServer
publicclassChargenServer {15
{15 16
16 publicstaticfinalintDEFAULT_PORT=8778;17
publicstaticfinalintDEFAULT_PORT=8778;17
 /** *//**18
/** *//**18 *@paramargs19
     *@paramargs19 */20
*/20
 publicstaticvoidmain(String[] args)
publicstaticvoidmain(String[] args) {21
{21 //TODO Auto-generated method stub22
//TODO Auto-generated method stub22 intport ;23
intport ;23 port=DEFAULT_PORT ;24
        port=DEFAULT_PORT ;24 25
25 byte[] rotation=newbyte[95*2] ;26
byte[] rotation=newbyte[95*2] ;26 for(bytei=''; i
for(bytei=''; i

 {28
{28 rotation[i-'']=i ;29
            rotation[i-'']=i ;29 rotation[i+95-'']=i ;30
            rotation[i+95-'']=i ;30 }31
        }31 32
32 ServerSocketChannel serverChannel=null;33
        ServerSocketChannel serverChannel=null;33 Selector selector=null;34
        Selector selector=null;34 35
35 36
36
 /** *//**37
/** *//**37 * 先建立服务器端的通道38
         * 先建立服务器端的通道38 *39
         *39 */40
*/40 41
41
 try
try {42
{42 serverChannel=ServerSocketChannel.open() ;43
            serverChannel=ServerSocketChannel.open() ;43 ServerSocket ss=serverChannel.socket() ;44
            ServerSocket ss=serverChannel.socket() ;44 InetSocketAddress address=newInetSocketAddress(port) ;45
            InetSocketAddress address=newInetSocketAddress(port) ;45 ss.bind(address) ;46
            ss.bind(address) ;46 serverChannel.configureBlocking(false) ;47
            serverChannel.configureBlocking(false) ;47 selector=Selector.open() ;48
            selector=Selector.open() ;48 serverChannel.register(selector, SelectionKey.OP_ACCEPT) ;49
            serverChannel.register(selector, SelectionKey.OP_ACCEPT) ;49 50
50 51
51 52
52
 }catch(IOException e)
        }catch(IOException e) {53
{53 //TODO Auto-generated catch block54
//TODO Auto-generated catch block54 e.printStackTrace();55
e.printStackTrace();55 }56
        }56 57
57 58
58 while(true)59
while(true)59

 {60
{60 61
61
 try
try {62
{62 selector.select() ;63
                selector.select() ;63
 }catch(IOException e)
            }catch(IOException e) {64
{64 e.printStackTrace();65
                e.printStackTrace();65 }66
            }66 67
67 Set readyKeys=selector.selectedKeys() ;68
            Set readyKeys=selector.selectedKeys() ;68 Iterator iter=readyKeys.iterator() ;69
            Iterator iter=readyKeys.iterator() ;69 while(iter.hasNext())70
while(iter.hasNext())70

 {71
{71 SelectionKey key=(SelectionKey) iter.next() ;72
                SelectionKey key=(SelectionKey) iter.next() ;72 iter.remove() ;73
                iter.remove() ;73 74
74 if(key.isAcceptable())75
if(key.isAcceptable())75

 {76
{76 ServerSocketChannel server=(ServerSocketChannel) key.channel() ;77
                    ServerSocketChannel server=(ServerSocketChannel) key.channel() ;77
 try
try {78
{78 SocketChannel client=server.accept() ;79
                        SocketChannel client=server.accept() ;79 System.out.println("Accept connection from"+client) ;80
                        System.out.println("Accept connection from"+client) ;80 client.configureBlocking(false) ;81
                        client.configureBlocking(false) ;81 SelectionKey key2=client.register(selector, SelectionKey.OP_WRITE) ;82
                        SelectionKey key2=client.register(selector, SelectionKey.OP_WRITE) ;82 ByteBuffer buffer=ByteBuffer.allocate(74) ;83
                        ByteBuffer buffer=ByteBuffer.allocate(74) ;83 buffer.put(rotation ,0,72) ;84
                        buffer.put(rotation ,0,72) ;84 buffer.put((byte)'\r') ;85
                        buffer.put((byte)'\r') ;85 buffer.put((byte)'\n') ;86
                        buffer.put((byte)'\n') ;86 buffer.flip() ;87
                        buffer.flip() ;87 key2.attach(buffer) ;88
                        key2.attach(buffer) ;88 89
89 90
90 91
91 92
92
 }catch(IOException e)
                    }catch(IOException e) {93
{93 //TODO Auto-generated catch block94
//TODO Auto-generated catch block94 e.printStackTrace();95
e.printStackTrace();95 }96
                    }96 97
97 98
98 99
99 100
100 }101
                }101 102
102 else103
else103 if(key.isWritable())104
if(key.isWritable())104

 {105
{105 106
106
 /** *//**107
/** *//**107 * 建立客户端通道108
                         * 建立客户端通道108 *109
                         *109 */110
*/110 SocketChannel client=(SocketChannel)key.channel() ;111
                        SocketChannel client=(SocketChannel)key.channel() ;111 ByteBuffer buffer=(ByteBuffer) key.attachment() ;112
                        ByteBuffer buffer=(ByteBuffer) key.attachment() ;112 if(!buffer.hasRemaining())113
if(!buffer.hasRemaining())113

 {114
{114 buffer.rewind() ;115
                            buffer.rewind() ;115 intfirst=buffer.get() ;116
intfirst=buffer.get() ;116 buffer.rewind() ;117
                            buffer.rewind() ;117 intposition=first-''+1;118
intposition=first-''+1;118 buffer.put(rotation , position ,72) ;119
                            buffer.put(rotation , position ,72) ;119 buffer.put((byte)'\r') ;120
                            buffer.put((byte)'\r') ;120 buffer.put((byte)'\n');121
                            buffer.put((byte)'\n');121 buffer.flip() ;122
                            buffer.flip() ;122 }123
                        }123
 try
try {124
{124 client.write(buffer) ;125
                            client.write(buffer) ;125
 }catch(IOException e)
                        }catch(IOException e) {126
{126 //TODO Auto-generated catch block127
//TODO Auto-generated catch block127 e.printStackTrace();128
e.printStackTrace();128 }129
                        }129 }130
                    }130 131
131 132
132 133
133 134
134 135
135 136
136 137
137 138
138 key.cancel() ;139
                key.cancel() ;139
 try
try {140
{140 key.channel().close() ;141
                    key.channel().close() ;141
 }catch(IOException e)
                }catch(IOException e) {142
{142 //TODO Auto-generated catch block143
//TODO Auto-generated catch block143 e.printStackTrace();144
e.printStackTrace();144 }145
                }145 }146
            }146 147
147 148
148 }149
        }149 150
150 151
151 152
152 153
153 154
154 155
155 156
156 157
157 158
158 }159
    }159 160
160 }161
}161
posted on 2010-08-01 21:19 buptduming 阅读(4114) 评论(0) 编辑 收藏