Java 网络编程之NioSocket

来源:互联网 发布:蜘蛛纸牌算法 编辑:程序博客网 时间:2024/06/05 05:41

        从Jdk1.4开始,Java增加了新的Io模式---nio(new io),nio在底层采用了新的处理方式,极大的提高了IO的效率。我们使用的Socket也是IO的一种,nio提供了响应的工具:ServerSocketChanner和SocketChannel,它们分别对应原来的ServerSocket和Socket.

        NioSokcet中服务端的处理过程可以分为5步:

1)创建ServerSocketChannel并设置相应的参数。

2)创建Selector并注册到ServerSocketChannel上。

3)调用Selector的select方法等待请求。

4)Select接收到请求后使用selectdKeys返回SelectionKey集合。

5)使用SelectionKey获取到Channel、Selector和操作类型并做相应的操作。

        现在将前面例子的Server改为使用nio方式进行处理的NIOServer. Client端参考链接例子。链接

import java.io.IOException;import java.net.InetSocketAddress;import java.nio.ByteBuffer;import java.nio.channels.SelectionKey;import java.nio.channels.Selector;import java.nio.channels.ServerSocketChannel;import java.nio.channels.SocketChannel;import java.nio.charset.Charset;import java.util.Iterator;public class NIOServer {public static void main(String[] args) throws Exception {//创建ServerSocketChannel,监听8080端口ServerSocketChannel ssc = ServerSocketChannel.open();ssc.socket().bind(new InetSocketAddress(8080));//设置为非阻塞模式ssc.configureBlocking(false);//为ssc注册选择器Selector selector = Selector.open();ssc.register(selector, SelectionKey.OP_ACCEPT);//创建处理器Handler handler = new Handler(1024);while(true){//等待请求,每次等待阻塞3s,超过3s后线程继续向下运行,如果传入0或者不传入参数,将一直等待if(selector.select(3000)==0){System.out.println("等待请求超时......");continue;}System.out.println("处理请求....");//获取请求的SelectionKeyIterator<SelectionKey> keyIter = selector.selectedKeys().iterator();while(keyIter.hasNext()){SelectionKey key = keyIter.next();try {//接收到连接请求时if(key.isAcceptable()){handler.handleAccept(key);}//读数据if(key.isReadable()){handler.handleRead(key);}} catch (IOException e) {keyIter.remove();continue;}//处理完后,从待处理的SelectionKey迭代器中移除当前所使用的keykeyIter.remove();}}}private static class Handler{private int bufferSize=1024;private String localCharset="UTF-8";public Handler(){}public Handler(int bufferSize){this(bufferSize,null);}public Handler(String localCharset){this(-1,localCharset);}public Handler(int bufferSize,String localCharset){if(bufferSize>0)this.bufferSize=bufferSize;if(localCharset!=null)this.localCharset=localCharset;}public void handleAccept(SelectionKey key) throws IOException{SocketChannel sc = ((ServerSocketChannel)key.channel()).accept();sc.configureBlocking(false);sc.register(key.selector(),SelectionKey.OP_READ,ByteBuffer.allocate(bufferSize));}public void handleRead(SelectionKey key) throws IOException{//获取channelSocketChannel sc=(SocketChannel)key.channel();//获取buffer并重置ByteBuffer buffer=(ByteBuffer)key.attachment();buffer.clear();//并没有读到内容则关闭if(sc.read(buffer)==-1){sc.close();}else{//将buffer转换为读状态buffer.flip();//将buffer中接受到的值按localCharset格式编码后保存到receivedStringString receivedString = Charset.forName(localCharset).newDecoder().decode(buffer).toString();System.out.println("received from client:"+receivedString);//返回数据给客户端String sendString="received from client:"+receivedString;buffer=ByteBuffer.wrap(sendString.getBytes(localCharset));sc.write(buffer);//关闭socketsc.close();}}}}

参考书籍:《看透Spring MVC源代码分析与实战》