非阻塞通信(服务器端)
来源:互联网 发布:鞋店销售软件 编辑:程序博客网 时间:2024/06/05 14:13
一.非阻塞
1.非阻塞:线程执行方法时,如果操作没有就绪,就立即返回,不会一直等待操作就绪
2.java.nio提供非阻塞通信的类:
1)ServerSocketChannel:代替Server
2)SocketChannel:代替Socket
3)Selector:监控就绪事件
4)SelectionKey:注册事件的句柄
3.服务器端程序使用多线程处理阻塞IO,虽然可以响应多用户,但是存在局限性
1)JVM会给每个线程分配独立的资源,线程越多,系统开销越大
2)容易造成死锁
3)需要频繁转让CPU使用
4.完成多个任务可以使用多线程分别处理,也可以让单个线程以轮询的工作方式处理就绪的任务
二.创建非阻塞服务器端程序
对于服务区端造成阻塞的原因有:
1)客户端的连接
2)接收客户端的数据
3)响应客户端的数据
所以,可以在主线程中分别监控这些任务,当有任何一个就绪就执行
public class nio_demo2 { private Selector selector = null; private ServerSocketChannel serverSocketChannel = null; private int port = 6666; private Charset charset = Charset.forName("UTF-8"); public nio_demo2() throws IOException { selector = Selector.open(); serverSocketChannel = ServerSocketChannel.open(); serverSocketChannel.socket().setReuseAddress(true); serverSocketChannel.configureBlocking(false); serverSocketChannel.socket().bind(new InetSocketAddress(port)); System.out.println("server start..."); } public void service() throws IOException { serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT); //select():监控注册的channel,当有需要处理的IO时,将对应的selectionKey加入到selected-key集合 while(selector.select()>0){ Set readyKey = selector.selectedKeys(); Iterator it = readyKey.iterator(); while(it.hasNext()){ SelectionKey key = null; try{ key = (SelectionKey)it.next(); it.remove(); if(key.isAcceptable()){ ServerSocketChannel ssc = (ServerSocketChannel)key.channel(); SocketChannel socketChannel = ssc.accept(); System.out.println("client connection" + socketChannel.socket().getInetAddress()+":" +socketChannel.socket().getPort()); //设置为非阻塞 socketChannel.configureBlocking(false); ByteBuffer buffer = ByteBuffer.allocate(1024); //向selecctor注册读就绪事件和写就绪时件,同时关联buffer socketChannel.register(selector, SelectionKey.OP_READ|SelectionKey.OP_WRITE,buffer); } if(key.isReadable()){ receive(key); } if(key.isWritable()){ send(key); } }catch (IOException e){ e.printStackTrace(); try{ if(key!=null){ key.cancel(); key.channel().close(); } }catch(Exception ex){ ex.printStackTrace(); } } } } } //发送,处理写就绪事件 public void send(SelectionKey key) throws IOException { //获得关联的附件 ByteBuffer buffer = (ByteBuffer)key.attachment(); SocketChannel socketChannel = (SocketChannel)key.channel(); buffer.flip(); String data = decode(buffer); if(data.indexOf("\n")==-1){ return; } String outputData = data.substring(0,data.indexOf("\n")+1); System.out.println(outputData); ByteBuffer outputBuffer = encode("echo:"+outputData); //发送一行数据 while(outputBuffer.hasRemaining()){ socketChannel.write(outputBuffer); } //删除已处理数据(读写操作同一个ByteBuffer) ByteBuffer temp = encode(outputData); buffer.position(temp.limit()); buffer.compact(); if(outputData.equals("end\n")){ key.cancel(); socketChannel.close(); System.out.println("close coonnection"); } } //接收,处理读就绪事件 public void receive(SelectionKey key) throws IOException { //获取关联的buffer ByteBuffer buffer = (ByteBuffer)key.attachment(); //获取关联的channel SocketChannel socketChannel = (SocketChannel)key.channel(); ByteBuffer readBuffer = ByteBuffer.allocate(32); socketChannel.read(readBuffer); //flip:将极限设置为位置,将位置设置为0 readBuffer.flip(); buffer.limit(buffer.capacity()); buffer.put(readBuffer); } //解码 public String decode(ByteBuffer buffer){ CharBuffer charBuffer = charset.decode(buffer); return charBuffer.toString(); } //编码 public ByteBuffer encode(String str){ return charset.encode(str); } public static void main(String[] args) throws IOException { nio_demo2 server = new nio_demo2(); server.service(); }}
阅读全文
0 0
- 非阻塞通信(服务器端)
- 阻塞和非阻塞通信
- 阻塞和非阻塞通信
- 阻塞和非阻塞通信
- 阻塞和非阻塞通信
- 阻塞和非阻塞通信
- 四. 非阻塞通信
- 非阻塞通信
- 非阻塞通信
- 非阻塞通信
- 四. 非阻塞通信
- java 非阻塞通信
- java非阻塞通信
- 非阻塞通信
- java 非阻塞通信
- java 非阻塞通信
- Java_nio_非阻塞通信
- 四. 非阻塞通信
- VMware Workstation安装Linux步骤详解
- 异步调用接口返回大量数据,如何处理才能使页面渲染时不卡?
- 数据库索引的作用和优点缺点以及索引的11中用法
- JavaScript事件
- Adventure Time URAL
- 非阻塞通信(服务器端)
- 集训8.8
- 数据结构——第一章 绪论
- 三目运算符优先级分析
- java map遍历方式
- bzoj 5243. 【GDOI2018模拟8.8】超级绵羊异或 类欧几里德算法
- 浏览器 返回状态码汇总
- 2017年8月8日21:10:15
- POJ