一、Selectors 挑选器
---------------------------------------------------------------------
1.Selectors:用于挑选通道感兴趣的方法是否发生,是selectkey的集合
2.SelectionKey:表示通道和selector之间的一种绑定,是对通道的一种封装
3.Selector.open(); //打开一个挑选器
4.SelectionKey register(Selector sel ,int ops); //(通道打点调用)给通道注册挑选器,并指定感兴趣的事件,返回唯一标识
-- ops: Selectionkey.OP_READ
-- ops: Selectionkey.OP_WRITE
-- ops: Selectionkey.OP_CONNECT
-- ops: Selectionkey.OP_ACCEPT
5.selector.select(); //开始挑选感兴趣的事件,阻塞的,返回值int 表示状态发生变化的通道数量
6.添加到selector中的通道必须是非阻塞的
7.挑选器是一个集合,里面可以保存很多的通道。采用轮询机制来查看这些通道是否发生了自己感兴趣的事件
8.可以通过 key.cancel() 删除指定sekey的通道
二、使用SocketChannel实现socket编程
-----------------------------------------------------------------------------
1.控制台输入语句,发送给服务器,并且得到服务器的回执
---------------------------------------------------------------------------------------------
------------------------------------1.Server端---------------------------------------------
---------------------------------------------------------------------------------------------
/**
* NIO:NioServer
*/
public class NioServer {
public static void main(String[] args) {
try {
//1.打开channel
ServerSocketChannel ssc = ServerSocketChannel.open();
//2.绑定ip
InetSocketAddress local = new InetSocketAddress("0.0.0.0", 8888);
ssc.bind(local);
//3.设置非阻塞模式
ssc.configureBlocking(false);
//4.打开挑选器
Selector st = Selector.open();
//5.给channel注册挑选器,并注册感兴趣事件accept
ssc.register(st, SelectionKey.OP_ACCEPT);
//6.开始挑选
while(true)
{
try {
//7.阻塞的,如果没有发生感兴趣的事件,就一直等待
st.select();
} catch (Exception e) {
// TODO: handle exception
}
//8.获取发生变化的key(key中封装有channel)
Set<SelectionKey> set = st.selectedKeys();
for (SelectionKey key : set) {
try {
//如果是accept,说明是服务器
if(key.isAcceptable())
{
//9.找到变化的channel
ServerSocketChannel scc1 = (ServerSocketChannel) key.channel();
//10.获取用于与客户端通信的SocketChannel
SocketChannel sc1 = scc1.accept();
sc1.configureBlocking(false);
//11.将得到的SocketChannel注册到挑选器中,设置感兴趣的事件
sc1.register(st, SelectionKey.OP_CONNECT |SelectionKey.OP_READ | SelectionKey.OP_WRITE );
}
//如果是可读的,那就读
if(key.isReadable())
{
SocketChannel sc1 = (SocketChannel) key.channel();
ByteBuffer dst = ByteBuffer.allocate(1024);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
while(sc1.read(dst) != 0)
{
dst.flip();
baos.write(dst.array(), 0, dst.limit());
dst.clear();
String str = new String(baos.toByteArray());
System.out.println("客户端说: " + str);
dst = ByteBuffer.allocate(1024);
str = new String("hello:" + str);
dst.put(str.getBytes());
dst.flip();
sc1.write(dst);
dst.clear();
}
baos.close();
}
} catch (Exception e) {
e.printStackTrace();
//如果出现了错误,回收掉key
key.cancel();
}
}
set.clear();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
---------------------------------------------------------------------------------------------
------------------------------------2.Client端---------------------------------------------
---------------------------------------------------------------------------------------------
/**
* Nio : Client
*/
public class NioClient {
public static void main(String[] args) {
try {
//打开socketChannel
SocketChannel sc = SocketChannel.open();
InetSocketAddress ip = new InetSocketAddress("localhost", 8888);
//要在设定非阻塞之前进行连接,因为要确保连接已经成功!
sc.connect(ip);
sc.configureBlocking(false);
//打开selector
Selector st = Selector.open();
sc.register(st, SelectionKey.OP_READ);
//给服务器发消息
new sender(sc).start();
//
ByteBuffer dst = ByteBuffer.allocate(1024) ;
while(true)
{
st.select();
while(sc.read(dst) != 0)
{
dst.flip();
String str = new String(dst.array(),0,dst.limit());
System.out.println("服务器回执:" + str);
dst.clear();
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
---------------------------------------------------------------------------------------------
------------------------------------3. 客户端消息发送器---------------------------------
---------------------------------------------------------------------------------------------
/**
* 客户端消息发送器
*/
public class sender extends Thread{
private SocketChannel sc = null;
public sender(SocketChannel sc) {
this.sc = sc;
}
@Override
public void run() {
try {
ByteBuffer src = ByteBuffer.allocate(1024);
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String str = null;
byte [] buf = null;
while((str = br.readLine()) != null)
{
src = ByteBuffer.allocate(1024);
buf = str.getBytes();
src.put(buf);
src.flip();
sc.write(src);
src.clear();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}