BIO、NIO、Netty演进
BIO
1.BIO: Blocking IO
2.serverSocket.accept()// 阻塞; 接收client socket会阻塞
3.bufferedReader.readLine(); //阻塞; 读取内容会阻塞
package com.io;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class SocketBIO {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(6666);
Socket socket = serverSocket.accept();// blocking
System.out.println("1.client connect server");
socket.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String str = bufferedReader.readLine();// blocking
System.out.println(str);
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
bufferedWriter.write(str);
bufferedWriter.flush();
while (true){
}
}
}
NIO
- NIO: None blocking io
- NIO: new io (buffer/channer/selector)的概念
不使用多路复用器的NIO
package com.io;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
public class SocketNIO {
public static void main(String[] args) throws Exception {
List<SocketChannel> clients = new LinkedList<>();
ServerSocketChannel ss = ServerSocketChannel.open();
ss.configureBlocking(false); // set blocking or not blocking
ss.bind(new InetSocketAddress(6666));
while (true){
Thread.sleep(1000);
SocketChannel client = ss.accept();
if(client == null){
System.out.println("client is null");
}else{
client.configureBlocking(false);
int port = client.socket().getPort();
System.out.println("client port is "+ port);
clients.add(client);
}
ByteBuffer byteBuffer = ByteBuffer.allocate(4096);
for(SocketChannel socketChannel : clients){
int num = socketChannel.read(byteBuffer);
if(num > 0){
byteBuffer.flip();
System.out.println(socketChannel.socket().getPort()+ " " + new String(byteBuffer.array()));
socketChannel.write(byteBuffer);
byteBuffer.clear();
}
}
}
}
}
使用多路复用器单线程
1.一个线程同时处理accept 和 reader请求
package com.io;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Iterator;
import java.util.Set;
public class SocketMultiplexingSingleThread {
ServerSocketChannel serverSocketChannel = null;
Selector selector = null;
private void init(){
try{
serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.configureBlocking(false);
serverSocketChannel.bind(new InetSocketAddress(6666));
selector = Selector.open();
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
}catch (IOException e){
e.printStackTrace();
}
}
private void start() {
this.init();
try{
while (true){
while (selector.select() >0){
Set<SelectionKey> selectionKeys = selector.selectedKeys();
Iterator<SelectionKey> iterator = selectionKeys.iterator();
while (iterator.hasNext()){
SelectionKey selectionKey = iterator.next();
iterator.remove();
if(selectionKey.isAcceptable()){
acceptableHandler(selectionKey);
}
if(selectionKey.isReadable()){
readerHandler(selectionKey);
}
}
}
}
}catch (IOException e){
e.printStackTrace();
}
}
private void acceptableHandler( SelectionKey selectionKey){
try{
ServerSocketChannel ssc = (ServerSocketChannel) selectionKey.channel();
SocketChannel sc = ssc.accept();
sc.configureBlocking(false);
ByteBuffer buffer = ByteBuffer.allocate(1024);
sc.register(selector, SelectionKey.OP_READ,buffer);
System.out.println("accept a client : " + sc.socket().getInetAddress().getHostName());
}catch (IOException e){
e.printStackTrace();
}
}
private void readerHandler(SelectionKey selectionKey){
try{
SocketChannel socketChannel = (SocketChannel) selectionKey.channel();
ByteBuffer buffer = (ByteBuffer)selectionKey.attachment();
buffer.clear();
int r = socketChannel.read(buffer);
if(r != -1){
System.out.println("received client "+socketChannel.socket().getInetAddress().getHostName()+" message:"+new String(buffer.array()));
buffer.flip();
socketChannel.write(buffer);
}else{
socketChannel.close();
}
}catch (IOException e){
e.printStackTrace();
}
}
public static void main(String[] args) throws Exception {
SocketMultiplexingSingleThread nioDemo = new SocketMultiplexingSingleThread();
nioDemo.start();
}
}
使用多路复用器,多线程
1.一个线程处理accept请求
2.其他两个线程处理read请求
package com.io;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Iterator;
import java.util.Set;
public class SocketMultiplexingSingleThread {
ServerSocketChannel serverSocketChannel = null;
Selector selector = null;
private void init(){
try{
serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.configureBlocking(false);
serverSocketChannel.bind(new InetSocketAddress(6666));
selector = Selector.open();
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
}catch (IOException e){
e.printStackTrace();
}
}
private void start() {
this.init();
try{
while (true){
while (selector.select() >0){
Set<SelectionKey> selectionKeys = selector.selectedKeys();
Iterator<SelectionKey> iterator = selectionKeys.iterator();
while (iterator.hasNext()){
SelectionKey selectionKey = iterator.next();
iterator.remove();
if(selectionKey.isAcceptable()){
acceptableHandler(selectionKey);
}
if(selectionKey.isReadable()){
readerHandler(selectionKey);
}
}
}
}
}catch (IOException e){
e.printStackTrace();
}
}
private void acceptableHandler( SelectionKey selectionKey){
try{
ServerSocketChannel ssc = (ServerSocketChannel) selectionKey.channel();
SocketChannel sc = ssc.accept();
sc.configureBlocking(false);
ByteBuffer buffer = ByteBuffer.allocate(1024);
sc.register(selector, SelectionKey.OP_READ,buffer);
System.out.println("accept a client : " + sc.socket().getInetAddress().getHostName());
}catch (IOException e){
e.printStackTrace();
}
}
private void readerHandler(SelectionKey selectionKey){
try{
SocketChannel socketChannel = (SocketChannel) selectionKey.channel();
ByteBuffer buffer = (ByteBuffer)selectionKey.attachment();
buffer.clear();
int r = socketChannel.read(buffer);
if(r != -1){
System.out.println("received client "+socketChannel.socket().getInetAddress().getHostName()+" message:"+new String(buffer.array()));
buffer.flip();
socketChannel.write(buffer);
}else{
socketChannel.close();
}
}catch (IOException e){
e.printStackTrace();
}
}
public static void main(String[] args) throws Exception {
SocketMultiplexingSingleThread nioDemo = new SocketMultiplexingSingleThread();
nioDemo.start();
}
}
Netty
三种线程模型
1.单线程
2.多线程
3.主从
单线程模型
package com.io;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
public class NettyIO {
public static void main(String[] args) {
NioEventLoopGroup boss = new NioEventLoopGroup(1);
ServerBootstrap boot = new ServerBootstrap();
try{
boot.group(boss,boss)
.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer<NioSocketChannel>() {
@Override
protected void initChannel(NioSocketChannel channel) throws Exception {
ChannelPipeline channelPipeline = channel.pipeline();
channelPipeline.addLast(null);
}
});
ChannelFuture future = boot.bind(6666).sync();
future.channel().closeFuture().sync();
}catch (Exception e){
e.printStackTrace();
}
}
static class MyBound extends ChannelInboundHandlerAdapter{
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
ctx.write(msg);
}
@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
ctx.flush();
}
}
}
多线程模型
package com.io;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
public class NettyIO {
public static void main(String[] args) {
NioEventLoopGroup boss = new NioEventLoopGroup(4);//多线程
ServerBootstrap boot = new ServerBootstrap();
try{
boot.group(boss,boss)
.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer<NioSocketChannel>() {
@Override
protected void initChannel(NioSocketChannel channel) throws Exception {
ChannelPipeline channelPipeline = channel.pipeline();
channelPipeline.addLast(null);
}
});
ChannelFuture future = boot.bind(6666).sync();
future.channel().closeFuture().sync();
}catch (Exception e){
e.printStackTrace();
}
}
static class MyBound extends ChannelInboundHandlerAdapter{
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
ctx.write(msg);
}
@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
ctx.flush();
}
}
}
主从模型
package com.io;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
public class NettyIO {
public static void main(String[] args) {
NioEventLoopGroup boss = new NioEventLoopGroup(2);
NioEventLoopGroup worker = new NioEventLoopGroup(2);
ServerBootstrap boot = new ServerBootstrap();
try{
boot.group(boss,worker ) //主从
.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer<NioSocketChannel>() {
@Override
protected void initChannel(NioSocketChannel channel) throws Exception {
ChannelPipeline channelPipeline = channel.pipeline();
channelPipeline.addLast(null);
}
});
ChannelFuture future = boot.bind(6666).sync();
future.channel().closeFuture().sync();
}catch (Exception e){
e.printStackTrace();
}
}
static class MyBound extends ChannelInboundHandlerAdapter{
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
ctx.write(msg);
}
@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
ctx.flush();
}
}
}