BIO:服务器实现模式为一个连接一个线程,即用户端有连接请求时服务器就需要启动一个线程进行处理,如果这个连接不做任何事情就会造成不必要的线程开销。
BIO简单示例
//服务端
public class BIOServer {
public static void main(String[] args) throws IOException {
//注册服务端端口为8888,通过accept()方法获取socket
ServerSocket serverSocket = new ServerSocket(8888);
Socket accept = serverSocket.accept();
//获取输入流,打印接收到的数据
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(accept.getInputStream()));
String msg = null;
while ((msg = bufferedReader.readLine()) != null){
System.out.println("服务端:"+msg);
}
}
}
//客户端
public class BIOClient {
public static void main(String[] args) throws IOException {
//连接服务端,new一个socket
Socket socket = new Socket("localhost",8888);
//通过输出流传递数据
OutputStream outputStream = socket.getOutputStream();
outputStream.write("hello world".getBytes());
outputStream.flush();
//需要关闭
socket.close();
}
}
多个客户端连接到一个服务端
public static void main(String[] args) throws IOException {
//服务端
//通过线程池来并发处理
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(10, 20, 10000L, TimeUnit.SECONDS, new ArrayBlockingQueue<>(100));
ServerSocket serverSocket = new ServerSocket(8888);
while (true){
Socket accept = serverSocket.accept();
threadPoolExecutor.submit(() -> {
try {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(accept.getInputStream()));
String msg = null;
while ((msg = bufferedReader.readLine()) != null){
System.out.println("服务端:"+msg);
}
} catch (IOException e) {
e.printStackTrace();
}
});
}
}
public static void main(String[] args) throws IOException {
ArrayList<Integer> list = new ArrayList<>();
for (int i = 0; i < 100; i++) {
list.add(i);
}
//通过parallelStream来模拟并发
list.parallelStream().forEach(o->{
try {
Socket socket = new Socket("localhost",8888);
OutputStream outputStream = socket.getOutputStream();
String s = "hello world : " + o;
outputStream.write(s.getBytes());
outputStream.flush();
socket.close();
System.out.println("发送消息:"+o);
} catch (IOException e) {
e.printStackTrace();
}
});
}
NIO:服务器实现模式为一个线程处理多个请求连接,即客户端发送的连接请求都会注册到多路复用器上,多路复用器轮询连接有io请求就进行处理。
NIO简单示例
//服务端
public class NIOServer {
public static void main(String[] args) throws IOException {
//创建通道,开启非阻塞,绑定端口
ServerSocketChannel channel = ServerSocketChannel.open();
channel.configureBlocking(false);
channel.bind(new InetSocketAddress(8888));
//创建选择器,注册通道
Selector selector = Selector.open();
channel.register(selector, SelectionKey.OP_ACCEPT);
//开始监听端口,select()方法是阻塞的
while (selector.select() > 0){
Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
while (iterator.hasNext()){
SelectionKey next = iterator.next();
//一定要删除,不然再一次进来会报错
iterator.remove();
if(next.isAcceptable()){
//如果这个是新注册的,需要加入到select里面
SocketChannel socketChannel = channel.accept();
socketChannel.configureBlocking(false);
socketChannel.register(selector, SelectionKey.OP_READ);
}else if(next.isReadable()){
//如果是来了消息,就读取数据
SocketChannel channel1 = (SocketChannel)next.channel();
ByteBuffer buffer = ByteBuffer.allocate(1024);
int read = channel1.read(buffer);
if(read > 0){
String msg = new String(buffer.array());
System.out.println("服务器接收到了消息:"+msg);
}
}
}
}
}
}
//客户端
public class NIOClient {
public static void main(String[] args) throws IOException, InterruptedException {
InetSocketAddress localhost = new InetSocketAddress("localhost", 8888);
SocketChannel channel = SocketChannel.open(localhost);
channel.configureBlocking(false);
String name = Thread.currentThread().getName();
Scanner scanner = new Scanner(System.in);
String line;
while ((line = scanner.nextLine()) != null){
String s = name + "说:" + line;
ByteBuffer wrap = ByteBuffer.wrap(s.getBytes());
if(!channel.finishConnect()){
while (!channel.finishConnect()){
Thread.sleep(100);
}
}
channel.write(wrap);
}
}
}