Sabemos que o modelo BIO tradicional é bloqueado ao aguardar a conexão do cliente. Se não houver dados durante a leitura dos dados, ele também é bloqueado, enquanto o NIO pode ser configurado para ser sem bloqueio. Sem mais delongas, basta olhar para o código:
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.TimeUnit;
public class NioServer {
public static void main(String[] args) throws Exception {
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
//服务端非阻塞
serverSocketChannel.configureBlocking(false);
serverSocketChannel.bind(new InetSocketAddress(8888));
List<SocketChannel> clients = new LinkedList<>();
while (true) {
TimeUnit.SECONDS.sleep(1);
SocketChannel client = serverSocketChannel.accept();
if (null == client) {
System.err.println("没有新的客户端连接.....");
} else {
//客户端非阻塞
client.configureBlocking(false);
System.err.println(client.socket());
clients.add(client);
}
ByteBuffer byteBuffer = ByteBuffer.allocate(4096);
for (SocketChannel socketChannel : clients) {
int num = socketChannel.read(byteBuffer);
if (num > 0) {
byteBuffer.flip();
byte[] bytes = new byte[byteBuffer.limit()];
byteBuffer.get(bytes);
String b = new String(bytes);
System.err.println(b);
byteBuffer.clear();
}
}
}
}
}
//Não-bloqueio do lado do servidor serverSocketChannel.configureBlocking(false); //Não-bloqueio do lado do cliente client.configureBlocking(false);
Essas duas linhas de código são muito importantes. serverSocketChannel.configureBlocking(false) é definido como true. Então, enquanto não houver conexão do cliente, SocketChannel client = serverSocketChannel.accept(); esta linha será bloqueada e não será impressa a cada segundo. Não "Há uma nova conexão de cliente....."
Até que um cliente esteja conectado via telnet:
No entanto, ele ainda continuará bloqueando e aguardando a próxima conexão do cliente. Restauramos a linha serverSocketChannel.configureBlocking(false) para false, definimos client.configureBlocking(false); como true e vemos o efeito:
Após a conexão do primeiro cliente, os dados devem ser inseridos, caso contrário a leitura estará sempre bloqueada.
Vamos retornar ambas as opções para false e, em seguida, jogá-las no sistema Linux para executar e ver as chamadas do sistema (como verificar as chamadas do sistema, há um artigo anterior sobre modelo BIO Modelo BIO em Java - blog CSDN ) :
Você pode ver que accept não bloqueia como NIO, mas retorna diretamente -1, write(2, "\346\262\241\346\234\211\346\226\260\347\232\204\345 \256 \242\346\210\267\347\253\257\350\277\236\346\216\245....", 32) = 32
Na verdade, esta linha gera a frase "Há uma nova conexão de cliente..."