同步阻塞式I/O模型

参考:《Netty权威指南》


同步阻塞式I/O,即BIO。

原理:服务器端通常由一个独立的Acceptor负责监听客户端的连接,它接收到客户端请求之后为每个请求创建一个新的线程进行链路处理,处理完成通过输出流返回应答给客户端,并销毁线程。是典型的 一请求一应答 模型。

缺点:缺乏弹性,当并发访问量增加,由于大量的开辟线程导致系统性能急剧下降,系统可能发生线程堆栈溢出、创建新线程失败等问题,最终导致宕机或者僵死。

         这种模型无法满足高并发的性能要求。

同步阻塞式I/O模型_第1张图片


同步阻塞式I/O创建的TimeServer服务:

(1)TimeServer.java

package com.tao.netty.bio;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * 
 * @author Tao
 *
 * 同步阻塞式I/O创建的TimeServer 服务端
 */
public class TimeServer {
	
	public static void main(String[] args) throws IOException {
		
		int port = 8080;	//默认端口号8080
		
		if(args != null && args.length > 0) {
			try {
				port = Integer.valueOf(args[0]);	//指定端口号
			} catch (NumberFormatException e) {
				e.printStackTrace();
			}	
		}
		
		ServerSocket server = null;	//服务器socket
		
		try {
			server = new ServerSocket(port);
			System.out.println("TimeServer启动了,端口号是" + port);
			Socket socket = null;
			//循环监听客户端的请求
			while(true) {
				socket = server.accept();//请求来到,创建给socket
				//创建一个新线程处理请求
				new Thread(new TimeServerHandler(socket)).start();
			}
		} catch (Exception e) {
			// TODO: handle exception
		} finally {
			if(server != null) {
				System.out.println("关闭TimeServer");
				server.close();
				server = null;
			}
		}	
	}	
}


(2)TimeServerHandler.java

package com.tao.netty.bio;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Date;

/**
 * 处理客户端请求的类
 * @author Tao
 *
 */
public class TimeServerHandler implements Runnable{
	
	private Socket socket;
	
	public TimeServerHandler(Socket socket) {
		this.socket = socket;
	}
	
	
	@Override
	public void run() {
		BufferedReader in = null;
		PrintWriter out = null;
		
		try {
			//在socket上建立输入输出
			in = new BufferedReader(new InputStreamReader(this.socket.getInputStream(), "utf-8"));
			out = new PrintWriter(this.socket.getOutputStream(), true);
			
			String currentTime = null;
			String body = null;
			
			while(true) {
				body = in.readLine();//读入一行
				if(body == null) {
					break;
				}
				System.out.println("TimeServer收到消息:" + body);
				
				//如果收到请求时间的命令则返回当前时间
				if("order:current time".equalsIgnoreCase(body)) {
					currentTime = new Date(System.currentTimeMillis()).toString();
				}else {
					currentTime = "无效的命令";
				}
				out.println(currentTime);
			}
			
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if(in != null) {
				try {
					in.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			
			if(out != null) {
				out.close();
				out = null;
			}
			
			if(this.socket != null) {
				try {
					this.socket.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				this.socket = null;
			}
		}	
	}
}


(3)TimeClient.java

package com.tao.netty.bio;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;

/**
 * 
 * @author Tao
 *
 * 客户端
 */
public class TimeClient {
	
	public static void main(String[] args) throws IOException {
		int port = 8080;
		
		if(args != null && args.length > 0) {
			try {
				port = Integer.valueOf(args[0]);
			} catch (NumberFormatException e) {
				e.printStackTrace();
			}
		}
		
		Socket socket = null;
		BufferedReader in = null;
		PrintWriter out = null;
		Scanner scanner = null;
		
		try {
			socket = new Socket("127.0.0.1", port);//连接服务器
			in = new BufferedReader(new InputStreamReader(socket.getInputStream(), "utf-8"));
			out = new PrintWriter(socket.getOutputStream(), true);
			
			scanner = new Scanner(System.in);
			
			while(true) {
				String line = scanner.nextLine();
				if(line.equalsIgnoreCase("exit")) {
					break;
				}
					
				out.println(line);
				
				String receive = in.readLine();
				System.out.println("收到服务器的响应:" + receive);
			}
		} catch (Exception e) {
			// TODO: handle exception
		} finally {
			if(scanner != null) {
				scanner.close();
			}
			
			if(in != null) {
				in.close();
			}
			
			if(out != null) {
				out.close();
			}
		}
	}
}

        下一节介绍一种“伪异步”的模型。它是通过线程池和消息队列技术来实现一个或多个线程处理N个客户端请求的模型,然而它的底层仍然使用的是同步阻塞I/O。


你可能感兴趣的:(java,同步阻塞式IO模型,Java,NIO编程(Netty框架))