1. 程式人生 > >同步阻塞式IO(BIO)--學習筆記

同步阻塞式IO(BIO)--學習筆記

執行緒模型如下:


採用BIO模式的socket服務端,通常由獨立的Acceptor執行緒負責監聽客戶端連線,如果沒有客戶端傳送連線,Accpetor 會一直處於阻塞狀態。在接收到客戶端請求後,建立一個執行緒來處理該請求,處理完成後可以通過輸出流回應客戶端,然後執行緒銷燬。執行緒和客戶端併發數相等。完全是一次請求一次應答模式。

如果你有少量的連線使用非常高的頻寬,一次傳送大量的資料,也許典型的BIO伺服器實現可能非常契合。對於高併發訪問,每次訪問建立一個新的執行緒處理顯然不可行。

以下是javaSocket 實現程式碼:

伺服器端全部測試程式碼:

package bioFrame.server;

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

import bioFrame.server.handler.StringServerHandler;

/**
 * 同步阻塞式IO,為每個連結建立一個執行緒
 * 
 * @author Mercy
 *
 */
public class ServerMain {

	public static int port = 9001;//預設監聽埠

	public static void main(String[] args){
		System.out.println("Server start……");
		ServerSocket serverSocket = null;
		try {
			serverSocket = new ServerSocket(port);
			while(true){
				Socket socket = serverSocket.accept();
				new Thread(new StringServerHandler(socket)).start();
			}
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if(serverSocket != null){
				try {
					serverSocket.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		
	}
	
}

StringServerHandler 用來解析收到的文字內容

package bioFrame.server.handler;

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

/**
 * 用於接收客戶端發來的文字訊息,輸出到控制檯,並返回給客戶端一個時間戳
 * @author Mercy
 *
 */
public class StringServerHandler implements Runnable{
	
	private Socket socket;
	
	public StringServerHandler(Socket socket) {
		this.socket = socket;
	}

	@Override
	public void run() {
		BufferedReader br = null;
		try {
			br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
			StringBuffer sb = new StringBuffer();
			while(br.ready()){//判斷是否已準備好被讀取
				sb.append(br.readLine());
			}
			
//			String content = br.readLine();
//			while(content != null){
//				sb.append(content);
//				content = br.readLine();//這裡會阻塞?
//			}
			System.out.println("Server recive :" + sb.toString());
			PrintWriter pw = new PrintWriter(socket.getOutputStream());
			pw.print(String.valueOf(System.currentTimeMillis()));
			pw.flush();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if(br != null){
				try {
					br.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
				br = null;
			}
			
			if(socket != null){
				if(!socket.isClosed()){
					try {
						socket.close();
					} catch (IOException e) {
						e.printStackTrace();
					}
					socket = null;
				}
			}
		}
		
		
	}

}


socket客戶端測試程式碼如下:
package bioFrame.client;

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

/**
 * 同步阻塞式IO,傳送文字內容給伺服器,讀取伺服器響應,並列印結果
 * @author Mercy
 *
 */
public class ClientMain {

	/**
	 * 要連線的伺服器埠
	 */
	private static int port = 9001;
	
	private static String ip = "127.0.0.1";
	
	public static void main(String[] args){
		Socket socket = null;
		try {
			socket = new Socket(ip,port);
			PrintWriter pw = new PrintWriter(socket.getOutputStream());
			pw.println("這裡是第一行內容");
			pw.println("這裡是第二行內容");
			pw.flush();
			BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
			System.out.println("client recive :" + bufferedReader.readLine());
			pw.close();
			bufferedReader.close();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if(socket != null){
				if(!socket.isClosed()){
					try {
						socket.close();
					} catch (IOException e) {
						e.printStackTrace();
					}
					socket = null;
				}
			}
		}
		
	}
}