1.网络编程:
基本模型是Client/Server模型,也就是两个进程之间进行相互通信,其中服务端提供位置信息(绑定的IP地址和监听端口),客户端通过连接操作向服务端监听的地址发起请求,通过三次握手建立连接,如果连接建立成功,双方就可以通过网络套接字(socket)进行通信
传统同步阻塞模型,ServerSocket负责绑定IP地址,启动监听端口,Socket负责发起连接操作。连接成功后,双方通过输入和输出流进行同步阻塞式通信
2.BIO(BlockIO同步阻塞模型)
<1>原理:服务端通常由一个独立的Acceptor线程负责监听客户端的连接,接收到客户端连接请求后为每个客户端创建一个新线程进行链路处理,处理完成之后通过输出流返回应答给客户端,最后线程销毁。典型的一请求一应答模型
<2>缺点:缺乏弹性伸缩能力,客户端并发量增加后,服务端线程个数和客户端并发访问数呈1:1正比关系
3.伪异步I/O编程
<1>原理:采用线程池和任务队列。当有客户端接入时,将客户端的Socket 封装成一个Task(实现Runnable),传送到后端的线程池进行处理,JDK的线程池维护一个消息队列和N个活跃线程对消息队列中的任务进行处理。由于线程池可以设置消息队列的大小和最大线程数,因此资源占用是可控的
<2>优点:采用线程池,避免了为了每个请求都创建一个独立线程造成的线程资源耗尽问题。
缺点:底层采用了同步阻塞模型,无法从根本解决问题
<3>代码示例:
1)服务端:
public class TimeServer {
public static void main(String[] args) {
int port=8080;
ServerSocket serverSocket=null;
try {
serverSocket=new ServerSocket(port);
Socket socket=null;
//创建io线程池
TimeHandlerExecutePool timeHandlerExecutePool=new TimeHandlerExecutePool(50, 10000);
while(true){
socket=serverSocket.accept();
timeHandlerExecutePool.execute(new TimeServerHandler(socket));
}
} catch (IOException e) {
e.printStackTrace();
}finally {
if(serverSocket!=null){
System.out.println("The time server close");
try {
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
serverSocket=null;
}
}
}
}
2)线程池:
public class TimeHandlerExecutePool {
private Executor executor;
//构造方法
public TimeHandlerExecutePool(int maxPoolSize,int queueSize){
executor=new ThreadPoolExecutor(Runtime.getRuntime().availableProcessors(), maxPoolSize, 120L, TimeUnit.SECONDS, new ArrayBlockingQueue<java.lang.Runnable>(queueSize));
}
public void execute(Runnable task){
executor.execute(task);
}
}
3)服务端封装线程处理器(用于传递给执行器执行)
public class TimeServerHandler implements Runnable {
private Socket socket;
public TimeServerHandler(Socket socket) {
super();
this.socket = socket;
}
@Override
public void run() {
BufferedReader in=null;
PrintWriter out=null;
try {
in=new BufferedReader(new InputStreamReader(socket.getInputStream()));
out=new PrintWriter(socket.getOutputStream(),true);
String currentTime=null;
String body=null;
while(true){
body=in.readLine();
if(null==body){
break;
}
System.out.println("The time server receive order:"+body);
currentTime="QUERY TIME ORDER".equalsIgnoreCase(body)?new Date(System.currentTimeMillis()).toString():"BAD ORDER";
out.println(currentTime);
}
} catch (IOException e) {
if(null!=in){
try {
in.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
if(null!=out){
out.close();
out=null;
}
if(socket!=null){
try {
socket.close();
} catch (IOException e1) {
e1.printStackTrace();
}
socket=null;
}
}
}
}
4)客户端代码:
public class TimeClient {
public static void main(String[] args) {
int port=8080;
Socket socket=null;
BufferedReader in=null;
PrintWriter out=null;
try {
socket=new Socket("127.0.0.1", port);
in=new BufferedReader(new InputStreamReader(socket.getInputStream()));
out=new PrintWriter(socket.getOutputStream(),true);
out.println("QUERY TIME ORDER");
System.out.println("Send order 2 server succeed");
String resp=in.readLine();
System.out.println("Now is :"+resp);
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}