我们先写好客户端和服务端代码
package c2;
import lombok.extern.slf4j.Slf4j;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.ArrayList;
import java.util.List;
@Slf4j
public class Server {
public static void main(String[] args) throws IOException {
ByteBuffer buffer = ByteBuffer.allocate(16);
ServerSocketChannel ssc = ServerSocketChannel.open();
ssc.bind(new InetSocketAddress(8080));
List<SocketChannel> channels = new ArrayList<>();
while (true){
log.debug("连接前---");
SocketChannel sc = ssc.accept();
log.debug("已连接---{}",sc);
channels.add(sc);
for(SocketChannel channel : channels){
log.debug("读取前---{}",channel);
channel.read(buffer);
buffer.flip();
while (buffer.hasRemaining()){
byte b = buffer.get();
System.out.print((char) b);
System.out.println();
}
buffer.clear();
log.debug("读取后---{}",channel);
}
}
}
}
public class Client {
public static void main(String[] args) throws IOException {
SocketChannel sc = SocketChannel.open();
sc.connect(new InetSocketAddress("localhost",8080));
System.in.read();
}
}
运行服务端 可以看到程序停在了连接前这里
因为accept默认是阻塞方法
以调式模式运行客户端让程序不结束运行 此时卡在了读取前
说明read也是一个阻塞方法
使用调式的评估表达式 发送一个消息
可以看到发送完后 服务端又等待下一次连接
同时如果我们继续发消息会发现无法被读取 因为accept认为没有新连接加入 产生了阻塞
所以我们会发现 在阻塞模式下 单线程很难正常工作
非阻塞模式设置服务端为非阻塞模式
ServerSocketChannel ssc = ServerSocketChannel.open();
ssc.configureBlocking(false);//非阻塞模式
完整代码
package c2;
import lombok.extern.slf4j.Slf4j;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.ArrayList;
import java.util.List;
@Slf4j
public class Server {
public static void main(String[] args) throws IOException {
ByteBuffer buffer = ByteBuffer.allocate(16);
ServerSocketChannel ssc = ServerSocketChannel.open();
ssc.configureBlocking(false);//非阻塞模式
ssc.bind(new InetSocketAddress(8080));
List<SocketChannel> channels = new ArrayList<>();
while (true){
SocketChannel sc = ssc.accept();//非阻塞模式 就算没有连接 就会返回null
if(sc != null){
log.debug("已连接---{}",sc);
sc.configureBlocking(false);//非阻塞模式 使read不再阻塞
channels.add(sc);
}
for(SocketChannel channel : channels){
int read = channel.read(buffer);//如果没有读到数据则返回0
if(read > 0){
buffer.flip();
while (buffer.hasRemaining()){
byte b = buffer.get();
System.out.print((char) b);
System.out.println();
}
buffer.clear();
log.debug("读取后---{}",channel);
}
}
}
}
}
这种方式可以解决问题 但是很明显关于消耗性能了