预备学习Netty,首先从JAVA的BIO,NIO,AIO开始,逐步切入到Netty的学习中
BIO也就是JAVA的同步阻塞IO实现,当客户端发现请求后会一直等待到服务端完成响应后结束本次通信过程。当客户端请救数量过多时会有明显的效率问题,但对于简单的通信实现(比如点对点的通信)很简洁实用。
BIO一般有两种实现方式,一种是1:1的实现方式,针对每个客户端的请求,服务端开启一个线程进行对应。
acceptor接受每个客户端的请求,然后开启一个线程进行应对。该线程应对完成后针对各自的请求线程进行回应
客户端实现
package netty.bio;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
/**
- BIO模式客户端实现
- @author [email protected]
-
*/
public class SocketClient {public static void main(String[] args) {
Socket socket = null; PrintWriter pw = null; try { socket = new Socket("127.0.0.1",9999); pw = new PrintWriter(socket.getOutputStream(),true); pw.println("Hello Socket"); socket.close(); } catch (UnknownHostException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block socket = null; pw = null; e.printStackTrace(); }finally{ if(socket!=null) { socket = null; } }
}
}
服务端实现
package netty.bio;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
/**
- BIO模式服务端实现
- @author [email protected]
-
*/
public class SocketServer {public static void main(String[] args) {
int port = 9999; //创建socket通信server ServerSocket server = null; try { server = new ServerSocket(port); //创建socket对象 Socket socket = null; while(true) { //acceptor socket = server.accept(); //开启一个处理线程 new Thread ( new SocketHandler(socket)).start(); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); }
}
}
package netty.bio;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
/**
- 定义实现Runnable接口的Socket处理器,用于在线程处理中使用
- @author [email protected]
-
*/
public class SocketHandler implements Runnable{private Socket socket = null;
public SocketHandler(Socket socket) {
this.socket = socket ;
}
@Override
public void run() {//对传入的数据进行读取处理 //读入对象 BufferedReader in = null; try { //读取输入流数据 in = new BufferedReader(new InputStreamReader(socket.getInputStream())); String info = null; while(true) { //如果已读完全部数据,跳出死循环 info = in.readLine(); System.out.println("接收信息:"+info+" "+System.currentTimeMillis()); if(info == null) { break; } } //关闭读入流,关闭Socket socket.close(); in.close(); } catch (IOException e) { if(in!=null) { try { in.close(); } catch (IOException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } } if(socket!=null) { try { socket.close(); } catch (IOException e1) { socket = null; e1.printStackTrace(); } } e.printStackTrace(); }
}
}
另一种BIO的实现方式是M:N,M是客户端请求数,N是服务器端处理线程数。在服务端建立一个连接池。通过配置该连接池的核心连接数,最大连接数以及等待队列数使服务端的连接数量得到控制。这种方式比1:1的BIO实现方式要安全一些,会避免客户端连接数量过多时导致服务器端资源耗尽。
客户端实现
package netty.vio;
/**
- BIO M:N 客客端实现
- @author [email protected]
-
*/
public class ClientThreadMain {public static void main(String[] args) {
for(int i=0;i<800;i++) { Thread t = new Thread(new SocketClient()); t.start(); }
}
}
在每个客户端线程中都单独连一次服务器
package netty.vio;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
/**
- BIO模式客户端实现
- @author [email protected]
-
*/
public class SocketClient implements Runnable{@Override
public void run() {
// TODO Auto-generated method stub
Socket socket = null;PrintWriter pw = null; try { socket = new Socket("127.0.0.1",9999); pw = new PrintWriter(socket.getOutputStream(),true); pw.println("Hello Socket"); socket.close(); } catch (UnknownHostException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block socket = null; pw = null; e.printStackTrace(); }finally{ if(socket!=null) { socket = null; } }
}
服务器端实现
package netty.vio;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
/**
- BIO M:N 模式服务端实现
- @author [email protected]
-
*/
public class SocketServer {public static void main(String[] args) {
int port = 9999; //创建socket通信server ServerSocket server = null; try { server = new ServerSocket(port); //创建socket对象 Socket socket = null; //开一个排队请求的线程池,最大线程数50,队列数1000 SocketHandlerPool socketHandlerPool = new SocketHandlerPool(50,1000); while(true) { //acceptor socket = server.accept(); // socketHandlerPool.execute(new SocketHandler(socket)); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); }
}
}
定义线程处理池
package netty.vio;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
- 定义排序业务请求的pool
- @author [email protected]
-
*/
public class SocketHandlerPool {private ExecutorService executorService;
//指定池的最大数量与排队的最大数量
public SocketHandlerPool(int poolSize,int queueSize) {/* * 池核心线程数 * corePoolSize --the number of threads to keep in the pool, * evenif they are idle, unless allow Core Thread TimeOut is set * 最大线程数 * maximumPoolSize -- the maximum number of threads to allow in the pool * 线程空闲时保持时间 * keepAliveTime -- when the number of threads is greater than the core, * this is the maximum time that excess idle threads will wait for new tasks before terminating. * 保持时间单位 * unit -- the time unit for the keepAliveTime argument * 队列数 * workQueue-- the queue to use for holding tasks before they areexecuted. This queue will hold only the Runnable tasks * submitted by the execute method. */ this.executorService = new ThreadPoolExecutor(4, poolSize, 100, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(queueSize));
}
public void execute(Runnable task) {
//实际执行任务
executorService.execute(task);
}
}
package netty.vio;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
/**
- 定义实现Runnable接口的Socket处理器,用于在线程处理中使用
- @author [email protected]
-
*/
public class SocketHandler implements Runnable{private Socket socket = null;
public SocketHandler(Socket socket) {
this.socket = socket ;
}
@Override
public void run() {//对传入的数据进行读取处理 //读入对象 BufferedReader in = null; try { //读取输入流数据 in = new BufferedReader(new InputStreamReader(socket.getInputStream())); String info = null; while(true) { //如果已读完全部数据,跳出死循环 info = in.readLine(); System.out.println("接收信息:"+info+" "+System.currentTimeMillis()); if(info == null) { break; } } //关闭读入流,关闭Socket socket.close(); in.close(); } catch (IOException e) { if(in!=null) { try { in.close(); } catch (IOException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } } if(socket!=null) { try { socket.close(); } catch (IOException e1) { socket = null; e1.printStackTrace(); } } e.printStackTrace(); }
}
}
以上就是JAVA中BIO的基本实现,稍后继续进行AIO和NIO的实现,逐渐过渡到Netty的实现