jdk供的无阻塞I/O(NIO)有效解决了多线程服务器存在的线程开销问题,但在使用上略显得复杂一些。在NIO中使用多线程,主要目的已不是为了应对每个客户端请求而分配独立的服务线程,而是通过多线程充分使用用多个CPU的处理能力和处理中的等待时间,达到提高服务能力的目的。
从最简单的Hello World开始,client多线程请求server端,server接收client的名字,并返回Hello! +名字的字符格式给client。当然实际应用并不这么简单,实际可能是访问文件或者数据库获取信息返回给client。非阻塞的NIO有何神秘之处?代码:
1)server端代码
server主要是读取client发过来的信息,并返回一条信息
2)client端代码
从最简单的Hello World开始,client多线程请求server端,server接收client的名字,并返回Hello! +名字的字符格式给client。当然实际应用并不这么简单,实际可能是访问文件或者数据库获取信息返回给client。非阻塞的NIO有何神秘之处?代码:
1)server端代码
- /**
- *
- *@authorJeff
- *
- */
- publicclassHelloWorldServer{
- staticintBLOCK=1024;
- staticStringname="";
- protectedSelectorselector;
- protectedByteBufferclientBuffer=ByteBuffer.allocate(BLOCK);
- protectedCharsetDecoderdecoder;
- staticCharsetEncoderencoder=Charset.forName("GB2312").newEncoder();
- publicHelloWorldServer(intport)throwsIOException{
- selector=this.getSelector(port);
- Charsetcharset=Charset.forName("GB2312");
- decoder=charset.newDecoder();
- }
- //获取Selector
- protectedSelectorgetSelector(intport)throwsIOException{
- ServerSocketChannelserver=ServerSocketChannel.open();
- Selectorsel=Selector.open();
- server.socket().bind(newInetSocketAddress(port));
- server.configureBlocking(false);
- server.register(sel,SelectionKey.OP_ACCEPT);
- returnsel;
- }
- //监听端口
- publicvoidlisten(){
- try{
- for(;;){
- selector.select();
- Iteratoriter=selector.selectedKeys().iterator();
- while(iter.hasNext()){
- SelectionKeykey=(SelectionKey)iter.next();
- iter.remove();
- process(key);
- }
- }
- }catch(IOExceptione){
- e.printStackTrace();
- }
- }
- //处理事件
- protectedvoidprocess(SelectionKeykey)throwsIOException{
- if(key.isAcceptable()){//接收请求
- ServerSocketChannelserver=(ServerSocketChannel)key.channel();
- SocketChannelchannel=server.accept();
- //设置非阻塞模式
- channel.configureBlocking(false);
- channel.register(selector,SelectionKey.OP_READ);
- }elseif(key.isReadable()){//读信息
- SocketChannelchannel=(SocketChannel)key.channel();
- intcount=channel.read(clientBuffer);
- if(count>0){
- clientBuffer.flip();
- CharBuffercharBuffer=decoder.decode(clientBuffer);
- name=charBuffer.toString();
- //System.out.println(name);
- SelectionKeysKey=channel.register(selector,
- SelectionKey.OP_WRITE);
- sKey.attach(name);
- }else{
- channel.close();
- }
- clientBuffer.clear();
- }elseif(key.isWritable()){//写事件
- SocketChannelchannel=(SocketChannel)key.channel();
- Stringname=(String)key.attachment();
- ByteBufferblock=encoder.encode(CharBuffer
- .wrap("Hello!"+name));
- channel.write(block);
- //channel.close();
- }
- }
- publicstaticvoidmain(String[]args){
- intport=8888;
- try{
- HelloWorldServerserver=newHelloWorldServer(port);
- System.out.println("listeningon"+port);
- server.listen();
- }catch(IOExceptione){
- e.printStackTrace();
- }
- }
- }
server主要是读取client发过来的信息,并返回一条信息
2)client端代码
- /**
- *
- *@authorJeff
- *
- */
- publicclassHelloWorldClient{
- staticintSIZE=10;
- staticInetSocketAddressip=newInetSocketAddress("localhost",8888);
- staticCharsetEncoderencoder=Charset.forName("GB2312").newEncoder();
- staticclassMessageimplementsRunnable{
- protectedStringname;
- Stringmsg="";
- publicMessage(Stringindex){
- this.name=index;
- }
- publicvoidrun(){
- try{
- longstart=System.currentTimeMillis();
- //打开Socket通道
- SocketChannelclient=SocketChannel.open();
- //设置为非阻塞模式
- client.configureBlocking(false);
- //打开选择器
- Selectorselector=Selector.open();
- //注册连接服务端socket动作
- client.register(selector,SelectionKey.OP_CONNECT);
- //连接
- client.connect(ip);
- //分配内存
- ByteBufferbuffer=ByteBuffer.allocate(8*1024);
- inttotal=0;
- _FOR:for(;;){
- selector.select();
- Iteratoriter=selector.selectedKeys().iterator();
- while(iter.hasNext()){
- SelectionKeykey=(SelectionKey)iter.next();
- iter.remove();
- if(key.isConnectable()){
- SocketChannelchannel=(SocketChannel)key
- .channel();
- if(channel.isConnectionPending())
- channel.finishConnect();
- channel
- .write(encoder
- .encode(CharBuffer.wrap(name)));
- channel.register(selector,SelectionKey.OP_READ);
- }elseif(key.isReadable()){
- SocketChannelchannel=(SocketChannel)key
- .channel();
- intcount=channel.read(buffer);
- if(count>0){
- total+=count;
- buffer.flip();
- while(buffer.remaining()>0){
- byteb=buffer.get();
- msg+=(char)b;
- }
- buffer.clear();
- }else{
- client.close();
- break_FOR;
- }
- }
- }
- }
- doublelast=(System.currentTimeMillis()-start)*1.0/1000;
- System.out.println(msg+"usedtime:"+last+"s.");
- msg="";
- }catch(IOExceptione){
- e.printStackTrace();
- }
- }
- }
- publicstaticvoidmain(String[]args)throwsIOException{
- Stringnames[]=newString[SIZE];
- for(intindex=0;index<SIZE;index++){
- names[index]="jeff["+index+"]";
- newThread(newMessage(names[index])).start();
- }
- }
- }