您好,登錄后才能下訂單哦!
這篇文章將為大家詳細講解有關Java中怎么實現BIO阻塞式網絡編程,文章內容質量較高,因此小編分享給大家做個參考,希望大家閱讀完這篇文章后對相關知識有一定的了解。
阻塞(blocking)IO :阻塞是指結果返回之前,線程會被掛起,函數只有在得到結果之后(或超時)才會返回
非阻塞(non-blocking)IO :非阻塞和阻塞的概念相對應,指在不能立刻得到結果之前,該函數不會阻塞當前線程,而會立刻返回
同步(synchronous)IO :應用阻塞在發送或接受數據的狀態,直至數據成功傳輸(或返回失敗),簡單來說就是必須一件一件事做,等前一件做完了才能做下一件事
異步(asynchronous)IO :應用發送或接受數據后立即返回,實際處理這個調用的程序在完成后,通過狀態、通知和回調來通知調用者
阻塞和非阻塞是獲取資源的方式,同步和異步是程序如何處理資源的邏輯。
首先我們來看一段最基礎的Java網絡編程代碼示例:
服務器端代碼示例:
public class BIOServerV1 { public static void main(String[] args) throws Exception { ServerSocket serverSocket = new ServerSocket(8080); System.out.println("服務器啟動成功"); while (!serverSocket.isClosed()) { Socket request = serverSocket.accept(); // 阻塞 System.out.println("收到新連接:" + request.toString()); try { InputStream inputStream = request.getInputStream(); // 獲取數據流 BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream, "utf-8")); String message; while ((message = bufferedReader.readLine()) != null) { if (message.length() == 0) { break; } System.out.println("消息內容為:" + message); } System.out.println("收到數據,來自:" + request.toString()); } catch (IOException e) { e.printStackTrace(); } finally { request.close(); } } serverSocket.close(); } }
客戶端代碼示例:
public class BIOClient { public static void main(String[] args) throws IOException { Socket socket = new Socket("localhost", 8080); OutputStream outputStream = socket.getOutputStream(); Scanner scanner = new Scanner(System.in); System.out.println("請輸入:"); String message = scanner.nextLine(); outputStream.write(message.getBytes(Charset.forName("UTF-8"))); scanner.close(); socket.close(); } }
這個版本服務器端的代碼同一時刻只能支持一個網絡連接,在建立連接之后服務端線程會被阻塞,只有在已建立連接的客戶端處理完數據關閉連接之后,后續的連接請求才能一個一個的處理,而為了能并發的處理多個請求我們在下一個版本中加入多線程的代碼。
public class BIOServerV2 { private static ExecutorService executorService = Executors.newCachedThreadPool(); public static void main(String[] args) throws IOException { ServerSocket serverSocket = new ServerSocket(8080); System.out.println("服務器啟動成功"); while (!serverSocket.isClosed()) { Socket request = serverSocket.accept(); System.out.println("收到新連接:" + request.toString()); // 多線程接收多個連接 executorService.submit( () -> { try { InputStream inputStream = request.getInputStream(); BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream, "utf-8")); String message; while ((message = bufferedReader.readLine()) != null) { if (message.length() == 0) { break; } System.out.println("消息內容為:" + message); } System.out.println("收到數據,來自:" + request.toString()); } catch (IOException e) { e.printStackTrace(); } finally { try { request.close(); } catch (IOException e) { e.printStackTrace(); } } }); } serverSocket.close(); } }
這個版本的代碼在加入多線程后可以并發的處理多個連接,但是它只能處理Java客戶端的連接不能處理瀏覽器端的連接,而為了能與瀏覽器端交互我們需要了解HTTP協議的內容。
HTTP協議請求數據包解析
HTTP協議響應數據包解析
HTTP協議響應狀態碼:
在了解了HTTP協議的內容之后我們就可以依據HTTP協議的內容編寫程序來處理瀏覽器請求。在之前多線程版本的代碼之上我們需要對數據根據HTTP協議的內容進行處理,代碼示例如下:
public class BIOServerV3 { private static ExecutorService executorService = Executors.newCachedThreadPool(); public static void main(String[] args) throws IOException { ServerSocket serverSocket = new ServerSocket(8080); System.out.println("服務器啟動成功"); while (!serverSocket.isClosed()) { Socket request = serverSocket.accept(); System.out.println("收到新連接:" + request.toString()); // 多線程接收多個連接 executorService.submit( () -> { try { InputStream inputStream = request.getInputStream(); BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream, "utf-8")); String message; while ((message = bufferedReader.readLine()) != null) { if (message.length() == 0) { break; } // 拿到消息后可以解析消息拿到請求方法,請求數據等內容 System.out.println("消息內容為:" + message); } System.out.println("收到數據,來自:" + request.toString()); // 根據HTTP協議響應數據包返回數據給瀏覽器 OutputStream outputStream = request.getOutputStream(); outputStream.write("HTTP/1.1 200 OK\r\n".getBytes()); outputStream.write("Content-Length: 11\r\n\r\n".getBytes()); outputStream.write("Hello World".getBytes()); outputStream.flush(); } catch (IOException e) { e.printStackTrace(); } finally { try { request.close(); } catch (IOException e) { e.printStackTrace(); } } }); } serverSocket.close(); } }
關于Java中怎么實現BIO阻塞式網絡編程就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。