java selector使用select轮询注册到selector中的channel,如果有channel准备好注册的事件,select()返回,返回值为可以操作的channel的个数。通过selector.selectedKeys()返回选中的key的集合。遍历集合中所有的key,判断key的事件,进行相应的处理,并从集合中remove掉。

客户端selector的使用逻辑与服务端selector使用逻辑几乎一致。

Server代码中监听了两个端口8888和8889两个端口,并注册到selector中。读取客户端发送的信息,并发送信息到客户端

Client代码向服务器对应的端口号发送信息,并接收服务器端返回的信息

这里我服务端用了channel+selector客户端直接用的socket,可以发送给服务端信息,但接收服务端信息没有接收到(代码没有贴出来)

PS:使用selector+channel可以在一个线程内监听多个channel,下面代码中就监听了两个端口的channel

SelectorServer.java

 import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
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.util.Iterator;
import java.util.Set; /**
* Created by 58 on 2016/11/28.
*/
public class SelectorServer {
public static void main(String args[]){
startServer();
}
public static ByteBuffer sendBuffer = ByteBuffer.allocate(1024);
public static ByteBuffer receiveBuffer = ByteBuffer.allocate(1024); public static void startServer(){
//用两个channel监听两个端口
int listenPort = 8888;
int listenPort1 = 8889;
sendBuffer.put("message from server".getBytes()); try {
//创建serverchannel,绑定对应的端口
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
ServerSocket serverSocket = serverSocketChannel.socket();
InetSocketAddress inetSocketAddress = new InetSocketAddress(listenPort);
serverSocket.bind(inetSocketAddress); //创建第二个channel
ServerSocketChannel serverSocketChannel1 = ServerSocketChannel.open();
ServerSocket serverSocket1 = serverSocketChannel1.socket();
InetSocketAddress inetSocketAddress1 = new InetSocketAddress(listenPort1);
serverSocket1.bind(inetSocketAddress1); //创建selector对象
Selector selector = Selector.open(); //设置channel注册到selector中
serverSocketChannel.configureBlocking(false);
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT); //第二个channel
serverSocketChannel1.configureBlocking(false);
serverSocketChannel1.register(selector, SelectionKey.OP_ACCEPT); System.out.println("start to listen port: " + listenPort);
System.out.println("start to listen port: " + listenPort1); //监听端口
while(true){
int readyChannels = selector.select();
if(readyChannels == 0)
continue;
Set<SelectionKey> selectedKeys = selector.selectedKeys();
Iterator<SelectionKey> iterator = selectedKeys.iterator();
while(iterator.hasNext()){
SelectionKey selectionKey = iterator.next();
dealSelectionKey(selector, selectionKey); iterator.remove();
}//while
}//while } catch (IOException e) {
e.printStackTrace();
}
} public static void dealSelectionKey(Selector selector, SelectionKey selectionKey){
try{
//准备好接收新的连接
if(selectionKey.isAcceptable()){
ServerSocketChannel serverSocketChannel = (ServerSocketChannel) selectionKey.channel();
SocketChannel clientSocketChannel = serverSocketChannel.accept();
clientSocketChannel.configureBlocking(false);
clientSocketChannel.register(selector, SelectionKey.OP_READ | SelectionKey.OP_WRITE);
System.out.println("channel is ready acceptable");
}
else if(selectionKey.isConnectable()){
selectionKey.channel().register(selector, SelectionKey.OP_READ);
System.out.println("channel is connectable.");
}
else if(selectionKey.isReadable()){
//读去客户端内容
SocketChannel clientSocketChannel = (SocketChannel) selectionKey.channel();
receiveBuffer.clear();
clientSocketChannel.read(receiveBuffer);
selectionKey.interestOps(SelectionKey.OP_WRITE);
System.out.println("message from client is: " + new String(receiveBuffer.array()));
System.out.println("Thread id : " + Thread.currentThread().getId());
}
else if(selectionKey.isWritable()){
//向客户端写数据
SocketChannel clientSocketChannel = (SocketChannel) selectionKey.channel();
sendBuffer.flip();
System.out.println("sendBuffer = " + new String(sendBuffer.array()));
clientSocketChannel.write(sendBuffer);
selectionKey.interestOps(SelectionKey.OP_READ);
System.out.println("channle is writable.");
}//else if
}catch (Exception e){ }
}
}

SelectorClient.java

 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.SocketChannel;
import java.util.Iterator;
import java.util.Set; /**
* Created by 58 on 2016/11/28.
*/
public class SelectorClient {
public static void main(String args[]){
work();
} public static void work(){
int serverPort = 8888;
ByteBuffer sendBuffer = ByteBuffer.wrap("client message".getBytes());
ByteBuffer receiveBuffer = ByteBuffer.allocate(1024);
try {
//创建通道,设置通道注册到selector中
SocketChannel socketChannel = SocketChannel.open();
Selector selector = Selector.open(); socketChannel.configureBlocking(false);
socketChannel.register(selector, SelectionKey.OP_WRITE | SelectionKey.OP_READ | SelectionKey.OP_CONNECT);
socketChannel.connect(new InetSocketAddress("localhost", serverPort));
int executeTimes = 2;
//while
while(executeTimes > 0){
executeTimes--;
int reayChannelNum = selector.select();
if(reayChannelNum == 0){
continue;
}
Set<SelectionKey> setOfSelectionKey = selector.selectedKeys();
Iterator<SelectionKey> iterator = setOfSelectionKey.iterator();
while(iterator.hasNext()){
SelectionKey selectionKey = iterator.next();
SocketChannel socketChannel1 = (SocketChannel) selectionKey.channel();
iterator.remove();
if(selectionKey.isConnectable()){
if(socketChannel1.isConnectionPending()){
socketChannel1.finishConnect();
System.out.println("connection complete.");
socketChannel1.write(sendBuffer);
}
}//if isConnectable
else if(selectionKey.isReadable()){
receiveBuffer.clear();
socketChannel1.read(receiveBuffer);
receiveBuffer.flip();
System.out.println("message from server: " + new String(receiveBuffer.array())); }//else if readable
else if(selectionKey.isWritable()){
sendBuffer.flip();
socketChannel1.write(sendBuffer);
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}

java selector的更多相关文章

  1. Java——Selector

  2. 【Android XML】Android XML 转 Java Code 系列之 Selector(2)

    今天我们要把drawable下的selector的XML文件转换成Java代码.(打包进jar,不依赖apk) 在转换工具中的代码为: https://github.com/SickWorm/Andr ...

  3. 深入理解Java NIO

    初识NIO: 在 JDK 1. 4 中 新 加入 了 NIO( New Input/ Output) 类, 引入了一种基于通道和缓冲区的 I/O 方式,它可以使用 Native 函数库直接分配堆外内存 ...

  4. NIO的一些相关链接

    Architecture of a Highly Scalable NIO-Based Server Scalable IO in Java Tricks and Tips with NIO part ...

  5. 五种I/O 模式,select、epoll方法的理解,BIO、NIO、AIO理解 相关文章

    一.io方式 Linux网络编程 五种I/O 模式及select.epoll方法的理解 web优化必须了解的原理之I/o的五种模型和web的三种工作模式 五种I/O 模式——阻塞(默认IO模式),非阻 ...

  6. [转]MMORPG服务器架构

    MMORPG服务器架构 一.摘要 1.网络游戏MMORPG整体服务器框架,包括早期,中期,当前的一些主流架构2.网络游戏网络层,包括网络协议,IO模型,网络框架,消息编码等.3.网络游戏的场景管理,A ...

  7. Kafka实战分析(一)- 设计、部署规划及其调优

    1. Kafka概要设计 kafka在设计之初就需要考虑以下4个方面的问题: 吞吐量/延时 消息持久化 负载均衡和故障转移 伸缩性 1.1 吞吐量/延时 对于任何一个消息引擎而言,吞吐量都是至关重要的 ...

  8. IO 概括

    # 一.概览 Java 的 I/O 大概可以分成以下几类: - 磁盘操作:File- 字节操作:InputStream 和 OutputStream- 字符操作:Reader 和 Writer- 对象 ...

  9. Flume实战案例运维篇

    Flume实战案例运维篇 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.Flume概述 1>.什么是Flume Flume是一个分布式.可靠.高可用的海量日志聚合系统,支 ...

随机推荐

  1. Python实现——一元线性回归(最小二乘法)

    2019/3/24 线性回归--最小二乘法公式法 暂时用python成功做出来了图像,但是其中涉及到的公式还是更多的来自于网络,尤其是最小二乘法公式中的两个系数的求解,不过目前看了下书高数也会马上提及 ...

  2. 第9项:尽量使用try-with-resources而不是try-finally(Prefer try-with-resources to try-finally)

      Java库包含许多必须通过调用close方法手动关闭的资源. 示例包括InputStream,OutputStream和java.sql.Connection. 关闭资源经常被客户忽视,可预见的可 ...

  3. 扩展jQuery高亮网页中的文本选中

    <script type="text/javascript"> //1.扩展jQuery $.fn.selectRange = function (start, end ...

  4. rabbitmq消息消费者

    pom <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http:// ...

  5. 递归缓存技术,缓存机制Memoization

    先看一下代码: 再看一下执行时间: 可以看出第一个阶乘的执行时间是3ms,后面的由于缓存了之前的计算结果,所以直接返回结果. 原理就是缓存之前的计算,避免重复计算.关键在于建立缓存数组. 可以看一下执 ...

  6. 【DP】【单调队列】洛谷 P2216 [HAOI2007]理想的正方形 题解

        算是单调队列的复习吧,不是很难 题目描述 有一个$a\times b$的整数组成的矩阵,现请你从中找出一个$n\times n$的正方形区域,使得该区域所有数中的最大值和最小值的差最小. 输入 ...

  7. POJ - 3090 gcd水题

    大概题意就是求\(1 \le i,j \le n\)的\(gcd(i,j) = 1\)的个数+2(对于0的特判) 正解应该是欧拉函数或者高逼格的莫比乌斯反演 但数据实在太水直接打表算了 /*H E A ...

  8. 简单的html渲染模板引擎

    <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ...

  9. jsonProperty

    //说明:界面参数name需要为: employeeName,Json格式的话需要传入:employee_name @JsonProperty("employee_name") p ...

  10. linux 基础运维 之 Linux的闹钟

    1. linux 删除一个文件的权限要看文件所在的目录的权限 删除文件需要对对这个目录拥有w权限 修改文件 查看文件的内容需要对文件有rw权限 删除 创建一个文件 需要对文件坐在地目录拥有wx权限2. ...