1.阻塞模式
一个线程来处理多个连接显得力不从心
accept等待连接 是一个阻塞方法
read读取SocketChannel中的数据 是一个阻塞方法
/**
* 服务端
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
//建立一个缓冲区
ByteBuffer byteBuffer = ByteBuffer.allocateDirect(16);
//创建一个服务器
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
//给服务器绑定一个端口8000,让客户端来连接
serverSocketChannel.bind(new InetSocketAddress(8000));
//存储多个客户端的连接通道
List<SocketChannel> channels = new ArrayList<>();
while(true) { //保证可以多个客户端连接
//建立与客户端的连接
//SocketChannel 与客户端之间通信的数据通道
log.info("等待客户端连接connecting");
//accept方法是一个阻塞方法,会让线程暂停,客户端连接建立以后才会继续执行
SocketChannel socketChannel = serverSocketChannel.accept();
log.info("已连接connected...{}", socketChannel);
channels.add(socketChannel);
for (SocketChannel sc: channels ) {
//接受客户端发送的数据
log.info("等待客户端向SocketChannel中传输数据...{}", sc);
//read方法是一个阻塞方法,会让线程暂停
sc.read(byteBuffer);
byteBuffer.flip();//读模式
String byteBufferContent = StandardCharsets.UTF_8.decode(byteBuffer).toString();
log.info("byteBufferContent={}", byteBufferContent);
byteBuffer.clear();//写模式,从0开始
log.info("读完毕..{}", sc);
}
}
}
/**
* 客户端
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
SocketChannel socketChannel = SocketChannel.open();
//连接服务端,地址localhost:8000
socketChannel.connect(new InetSocketAddress("localhost", 8000));
//将hello字符串->byte[]->ByteBuffer->socketChannel
socketChannel.write(StandardCharsets.UTF_8.encode("hello"));
System.out.println("waiting...");
}
2.非阻塞模式
/**
* 服务端
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
//建立一个缓冲区
ByteBuffer byteBuffer = ByteBuffer.allocateDirect(16);
//创建一个服务器
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
//****ServerSocketChannel配置为非阻塞-默认是阻塞true,可以让accept方法变成非阻塞
serverSocketChannel.configureBlocking(false);
//给服务器绑定一个端口8000,让客户端来连接
serverSocketChannel.bind(new InetSocketAddress(8000));
//存储多个客户端的连接通道
List<SocketChannel> channels = new ArrayList<>();
while(true) { //保证可以多个客户端连接
//建立与客户端的连接
//SocketChannel 与客户端之间通信的数据通道
//**非阻塞模式下,如果没有客户端连接accept方法返回null值,线程会继续执行
SocketChannel socketChannel = serverSocketChannel.accept();
if(null != socketChannel) {
log.info("已连接connected...{}", socketChannel);
channels.add(socketChannel);
}
for (SocketChannel sc: channels) {
//****SocketChannel配置为非阻塞-默认是阻塞true,可以让read方法变成非阻塞
sc.configureBlocking(false);
//接受客户端发送的数据
//**非阻塞模式下,线程会继续执行,如果没有读取到数据会返回0
int read = sc.read(byteBuffer);
if(read > 0) {
byteBuffer.flip();//读模式
String byteBufferContent = StandardCharsets.UTF_8.decode(byteBuffer).toString();
log.info("byteBufferContent={}", byteBufferContent);
byteBuffer.clear();//写模式,从0开始
log.info("读完毕..{}", sc);
}
}
}
}
问题:非阻塞模式,会让线程一直在跑,太忙了,不能这么用。参考后续的Selector用法。