1.BIO的例子。
/**
* @author lilinshen
* @title bio (Blocking io) 同步阻塞io
* @description jdk1.4 io 都是bio
* @date 2018/8/21 15:02
*/
public class BIOServer {
public static void main(String[] args) {
server1();
}
/**
* 传统,只能是1对1
*/
public static void server1() {
ServerSocket server = null;
Socket socket = null;
InputStream in = null;
OutputStream out = null;
try {
server = new ServerSocket(8000);
System.out.println("服务端启动成功,监听端口为8000,等待客户端连接...");
socket = server.accept(); //阻塞 客户端
in = socket.getInputStream();
byte[] buffer = new byte[1024];
int len = 0;
//读取客户端的数据
while ((len = in.read(buffer)) > 0) {
System.out.println(new String(buffer, 0, len));
}
//向客户端写数据
out = socket.getOutputStream();
out.write("hello everybody!".getBytes());
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 多线程
*/
public static void server2() {
ServerSocket server = null;
try {
server = new ServerSocket(8000);
System.out.println("服务端启动成功,监听端口为8000,等待客户端连接...");
while (true) {
Socket socket = new Socket();
//针对每个连接创建一个线程,去处理io操作
//socket来了之后就创建线程 不合理
new Thread(new BIOServerHandler(socket)).start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 线程池
*/
public static void server3() {
ServerSocket server = null;
ExecutorService executorService = Executors.newFixedThreadPool(60);
try {
server = new ServerSocket(8000);
System.out.println("服务端启动成功,监听端口为8000,等待客户端连接...");
while (true) {
Socket socket = new Socket();
//使用线程池中的线程去执行每个对应的任务
executorService.execute(new BIOServerHandler(socket));
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* @author lilinshen
* @title bio serverhandler
* @description 请填写相关描述
* @date 2018/8/21 15:20
*/
public class BIOServerHandler implements Runnable {
private Socket socket;
public BIOServerHandler(Socket socket) {
this.socket = socket;
}
/**
* 当前线程要执行的任务
*/
@Override
public void run() {
InputStream in = null;
try {
in = socket.getInputStream();
byte[] buffer = new byte[1024];
int len = 0;
//读取客户端的数据
while ((len = in.read(buffer)) > 0) {
System.out.println(new String(buffer, 0, len));
}
//向客户端写数据
OutputStream out = socket.getOutputStream();
out.write("hello everybody!".getBytes());
} catch (IOException e) {
e.printStackTrace();
}
}
}
2.nio例子
/**
* @author lilinshen
* @title nio 同步非阻塞
* @description 是对bio的改进,但是api比较复杂。
* @date 2018/8/21 15:53
*/
public class NIOServer {
private int port;
private InetSocketAddress address = null;
private Selector selector;
public NIOServer(int port) {
try {
this.port = port;
address = new InetSocketAddress(this.port);
ServerSocketChannel server = ServerSocketChannel.open();
//服务器通道设置成非阻塞的模式
//server.configureBlocking(false);
server.socket().bind(address);
selector = Selector.open();
//每当有客户端连接上来的时候,默认它已经连接上来了
//而这个连接我需要记录一个它的状态 connected
server.register(selector, SelectionKey.OP_ACCEPT);
System.out.println("服务器启动成功:" + this.port);
} catch (IOException e) {
e.printStackTrace();
}
}
//Selector开始轮询
public void listen() {
try {
while (true) {
//accept()阻塞的,select()也是阻塞的
int wait = this.selector.select();
if (wait == 0) {
continue;
}
//SelectionKey代表的是客户端和服务端连接的一个关键
Set<SelectionKey> keys = this.selector.selectedKeys();
Iterator<SelectionKey> i = keys.iterator();
while (i.hasNext()) {
SelectionKey key = i.next();
//针对每一个客户端进行相应的操作
process(key);
i.remove();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
//处理每一个客户端 key
private void process(SelectionKey key) throws IOException {
ByteBuffer buffer = ByteBuffer.allocate(1024);
if (key.isAcceptable()) {
ServerSocketChannel server = (ServerSocketChannel) key.channel();
SocketChannel client = server.accept();
client.configureBlocking(false);
//客户端一旦连接上来 读写
//往这个selector上注册key read 接下来可以读
client.register(selector, SelectionKey.OP_READ);
} else if (key.isReadable()) {
SocketChannel client = (SocketChannel) key.channel();
int len = client.read(buffer);
//读取完成了
if (len > 0) {
buffer.flip(); //固定
String content = new String(buffer.array(), 0, len);
client.register(selector, SelectionKey.OP_WRITE);
System.out.println(content);
}
buffer.clear();
} else if (key.isWritable()) {
SocketChannel client = (SocketChannel) key.channel();
client.write(buffer.wrap("hello world".getBytes()));
client.close();
}
}
public static void main(String[] args) {
new NIOServer(8000).listen();
}
}
3.netty例子
/**
* @author lilinshen
* @title netty 异步非阻塞
* @description 是对nio的封装,新增了异步。
* @date 2018/8/21 16:44
*/
public class NettyServer {
/**
* netty 异步非阻塞
* 在nio中的selector.select() 使用了多线程。
*/
public static void server() {
//Boss线程
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(new HttpRequestEncoder());
ch.pipeline().addLast(new HttpRequestDecoder());
//添加自己的handler
//...
}
}).option(ChannelOption.SO_BACKLOG, 128).childOption(ChannelOption.SO_KEEPALIVE, true);
//绑定服务端口 阻塞的过程
System.out.println("服务端开启等待客户端连接...");
ChannelFuture f = b.bind(8000).sync();
//开始接收客户端
f.channel().closeFuture().sync();
} catch (Exception e) {
e.printStackTrace();
} finally {
// 优雅的推出程序
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
public static void main(String[] args) {
server();
}
}