传统的BIO - Blocking IO - 阻塞式IO
BIO的缺点
- 如果有大量的请求访问服务器,那么就要产生大量的线程去应对这些请求,导致服务器资源过于紧张
- 在完成一次任务的过程中需要创建大量的输入或者输出流。
- 数据通过流传输,无法实现定点操作
- 阻塞模式
NIO - New IO - 非阻塞式IO:Buffer,Channel,Selector — Buffer是容器,用于存储数据;Channel用于传输;Selector进行过滤。
Buffer - 缓冲区
用于进行数据的存储。操作的都是基本类型。
数据在操作的时候是根据操作位的位置决定。
限制位是决定操作位所能达到的最大下标
标记位<= 操作位<= 限制位<= 容量位
Channel - 通道
传输数据,基于缓冲区进行传输。可以进行双向传输。
Selector - 多路复用通道选择器
底层如果通过selector进行c/s通信的代码实现
ClientSelector类
public static void main(String[] args) throws IOException {
SocketChannel sc=SocketChannel.open();
sc.configureBlocking(false);
sc.connect(new InetSocketAddress("localhost", 8090));
Selector selc=Selector.open();
sc.register(selc, SelectionKey.OP_CONNECT);
while(true){
selc.select();
Set <SelectionKey> keys=selc.selectedKeys();
Iterator<SelectionKey> it=keys.iterator();
while(it.hasNext()){
SelectionKey key=it.next();
if(key.isConnectable()){
SocketChannel scx=(SocketChannel) key.channel();
while(!scx.finishConnect());
scx.register(selc, SelectionKey.OP_READ|SelectionKey.OP_WRITE);
}
if(key.isReadable()){
SocketChannel scx=(SocketChannel) key.channel();
ByteBuffer buffer=ByteBuffer.allocate(1024);
scx.read(buffer);
System.out.println(new String(buffer.array(),0,buffer.position()));
sc.register(selc, key.interestOps()^SelectionKey.OP_READ);
}
if(key.isWritable()){
SocketChannel scx=(SocketChannel) key.channel();
scx.write(ByteBuffer.wrap("你好服务器".getBytes()));
sc.register(selc,key.interestOps()^SelectionKey.OP_WRITE);
}
it.remove();
}
}
}
ServerSelector类
public static void main(String[] args) throws IOException {
ServerSocketChannel ssc=ServerSocketChannel.open();
ssc.bind(new InetSocketAddress(8090));
ssc.configureBlocking(false);
Selector selc=Selector.open();
ssc.register(selc, SelectionKey.OP_ACCEPT);
while(true){
selc.select();
Set <SelectionKey> keys=selc.selectedKeys();
Iterator<SelectionKey> it=keys.iterator();
while (it.hasNext()) {
SelectionKey key = it.next();
if(key.isAcceptable()){
ServerSocketChannel sscx=(ServerSocketChannel) key.channel();
SocketChannel sc=sscx.accept();
while(sc==null)
sc=sscx.accept();
sc.configureBlocking(false);
sc.register(selc, SelectionKey.OP_READ| SelectionKey.OP_WRITE);
}
if(key.isReadable()){
SocketChannel sc=(SocketChannel) key.channel();
ByteBuffer buffer=ByteBuffer.allocate(1024);
sc.read(buffer);
System.out.println(new String(buffer.array(),0,buffer.position()));
sc.register(selc,key.interestOps()^SelectionKey.OP_READ);
}
if(key.isWritable()){
SocketChannel sc=(SocketChannel) key.channel();
sc.write(ByteBuffer.wrap("你好客户端".getBytes()));
sc.register(selc, key.interestOps()^SelectionKey.OP_WRITE);
}
it.remove();
}
}
}