如何改造传统的BIO
-
改造BIO的核心思想
将原先的accept()设置为非阻塞,将每一次连接的对象存在在List集合中,每次遍历这个集合,读取客户端发送来的数据,再调用accept()方法,把原先的read()方法设置为非阻塞,把这连接存放在List集合中。 -
参考代码
package com.imooc.test;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.ArrayList;
import java.util.List;
public class TomcatServer {
static ByteBuffer byteBuffer = ByteBuffer.allocate(512);
static List<SocketChannel> channelList = new ArrayList<>();
public static void main(String[] args) {
try {
ServerSocketChannel serverSocket = ServerSocketChannel.open();
SocketAddress socketAddress = new InetSocketAddress("127.0.0.1",9098);
serverSocket.bind(socketAddress);
serverSocket.configureBlocking(false);//设置为非阻塞。
while(true){
for(SocketChannel socketChannel : channelList){
int read = socketChannel.read(byteBuffer);
if(read>0){
System.out.println("read ---------------111---"+read);
byteBuffer.flip();
byte [] bs =new byte[read];
byteBuffer.get(bs);
String content = new String(bs);
System.out.println("content ---------------222---"+content);
byteBuffer.flip();
}else if(read==-1){
//把它remove
System.out.println("断开连接,将它remove");
channelList.remove(socketChannel);
}
}
SocketChannel accept=serverSocket.accept();
if(accept!=null){
System.out.println("连接成功!");
accept.configureBlocking(false);
channelList.add(accept);
System.out.println(channelList.size()+"list---- size");
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
- 上述代码有什么问题?
- 这个for循环写在JVM上影响效率,应该写在内核(os)中。
- 存在无意义的for循环,暂时无法解决。(selector 和 epoll)