1、示例java
互聯網的發展使得設備之間的網絡通信必不可少,一般用的最多的傳輸層協議就是TCP協議。有以下場景:
有A、B兩個節點,A、B創建TCP鏈接後,A對B說了一百句話。數據庫
一、客戶端程序編程
public class SocketClient { public static void main(String[] args) throws Exception { Socket socket = new Socket("127.0.0.1", 8088); OutputStream os = socket.getOutputStream(); PrintWriter pw = new PrintWriter(os); for (int i = 0; i < 100; i++) { os.write("A".getBytes()); } pw.flush(); pw.close(); os.close(); socket.close(); } }
二、服務端程序網絡
public class SocketServer { public static void main(String[] args) throws Exception { ServerSocket serverSocket = new ServerSocket(8088); while (true) { Socket socket = serverSocket.accept(); InputStream is = socket.getInputStream(); int i = 0; byte[] b = new byte[10]; while (is.read(b) != -1) { i++; System.out.println(new String(b)); b = new byte[10]; } System.out.println("總數讀取次數" + i); is.close(); socket.close(); } } }
三、運行結果
總讀取次數老是少於100
2、問題
上面所述問題是很常見的場景,創建起一個長鏈接進行交互,列如RPC、NIO編程等等。
咱們但願的結果是,一次交互一次讀寫,上面實例運行結果少於100次,說明有些數據庫包被打包在一塊兒發送,這就引出了今天的話題,TCP粘包拆包。
3、TCP粘包拆包
TCP協議是「流」協議,沒有邊界,TCP是傳輸層協議,它並不知道應用層業務數據的真正含義,它會根據TCP緩衝區的具體大小來進行包的劃分,一個完整的包可能會被拆分紅多個包來傳輸,也可能多個包會被合併層一個大數據包來傳輸,這就是粘包和拆包。
4、可能出現的狀況
假設Client端向Server端發送A、B兩個數據包,可能出現如下狀況
一、服務端接收到A、B兩個獨立的數據包,沒有拆包和粘包,這種狀況是咱們大多數場景下但願的;
二、服務端一次性收到了AB兩個包,A、B兩包被粘在一塊兒發送過來;
三、A數據包被拆分紅A一、A2,服務端先收到A1包,後收到A2和B的合包,這就發生了拆包和粘包兩種狀況;
四、狀況最糟糕的是A、B兩包被屢次拆分,發送到服務端。
大多數狀況下,咱們但願一次交互,能拿到交互中傳遞的完整信息,那麼有哪些解決方案解決TCP傳輸過程當中的拆包與粘包問題呢?請關注《TCP粘包拆包二》。
socket
快樂源於分享。大數據
此博客乃做者原創, 轉載請註明出處 code