nio-selector - 处理可写事件
public class WriteServer{
public static void main(String[] args) throws IOException {
ServerSocketChannel ssc = ServerSocketChannel.open();
//设置为非阻塞模式
ssc.configureBlocking(false);
//需要一个选择器(避免无畏的轮询)
Selector selector = Selector.open();
ssc.register(selector,SelectionKey.OP_ACCEPT);//只关注accept事件就可以了
//监听端口
ssc.bind(new InetSocketAnddress(8080));
while(true){
selector.select();//有事件发生才会继续运行
Iterator<SelectionKey> iter = selector.selectedKeys().iterator();//拿到所有事件
while(iter.hasNext()){
SelectionKey key = iter.next();
iter.remove();//移除key
if(key.isAcceptable()){
SocketChannel sc = ssc,accept();//只有一个,可以这么干
sc.configureBlocking(false);
SelectionKey sckey = sc.register(selector,0,null);
sckey.interestOPs(SelectionKey.OP_READ);
//1.向客户端发送大量数据
StringBuilder sb = new StringBuilder();
for(int i=0; i<5000000; i++){
sb.append("a");
}
ByteBuffer buffer = Charset.defaultCharset().encode(sb.toString());
//2.返回值代表实际写入的字节数
int write = sc.write(buffer);
System.out.println(write);
//3.判断是否有剩余内容
while(buffer.hasRemaining()){
//4.关注可写事件
sckey.interestOPs(sckey.interestOPs() + SelectionKey.OP_WRITE);
// sckey.interestOPs(sckey.interestOPs() | SelectionKey.OP_WRITE);
//5.把未写完的数据挂到sckey上(一次写不完,才需要关联可写事件)
sckey.attach(buffer);
}
} else if(key.isWritable()){//可写了
Object attachment = key.attachment();//把buffer拿出来
SocketChannel channel = key.channel();
int write = sc.write(buffer);
System.out.println(write);
//6.清理操作
if(!buffer.hasRemaining()){
key.attach(null);//需要清除buffer,把上次关联的替换掉
key.interestOPs(key.interstOPs-SelectionKey.OP_WRITE);//在原来的基础上减掉新加的事件,,不需要关注可写事件
}
}
}
}
}
}
public class WriteClient{
public static void main(String[] args)throws IOException{
SocketChannel sc = SocketChannel.open();
sc.connect(new InetSocketAddress("localhost",8080));
//3.接收数据
int count = 0;//实际读到的字节数
while(true){
ByteBuffer buffer = ByteBuffer.allocate(1024*1024);//每次1M
count += sc.read(buffer);
System.out.println(count);
buffer.clear();
}
}
}