TCP粘包拆包二

1、TCP粘包拆包問題解決方案
    《TCP粘包拆包一》拋出了粘包拆包的問題,那麼有哪些解決方案呢?
    經常使用解決方案:
    一、固定消息長度,例如每一個報文長度500字節,不夠該長度的用特殊字符補齊,如空格、\001等,這種       方式會增長一些無用字符的傳遞,浪費網絡流量。
    二、包尾部追加特殊符號進行分割,這種方式若是傳輸的數據中有分割符號,還要進行轉義,增長編碼的     難度。
    三、消息分爲消息頭和消息體兩部分;
    四、開發複雜應用協議,如HTTP協議等java

2、示例
    咱們實現第三種方案來解決粘包拆包問題, 一個報文分兩塊,消息頭咱們用4個字節來存儲消息實體的字節數,編碼實現以下:
一、客戶端代碼程序員

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++) {
			byte[] head = intToBytes("A".getBytes().length);
			// 消息實體的長度是用消息頭和消息體組成
			byte[] message = new byte[head.length + "A".getBytes().length];
			System.arraycopy(head, 0, message, 0, head.length);
			System.arraycopy("A".getBytes(), 0, message, head.length, "A".getBytes().length);
			os.write(message);
		}
		pw.flush();
		pw.close();
		os.close();
		socket.close();
	}

	// int型轉字節數組,java裏int用4字節表示,因此返回的字節數組長度爲4
	public static byte[] intToBytes(int value) {
		byte[] src = new byte[4];
		src[0] = (byte) ((value >> 24) & 0xFF);
		src[1] = (byte) ((value >> 16) & 0xFF);
		src[2] = (byte) ((value >> 8) & 0xFF);
		src[3] = (byte) (value & 0xFF);
		return src;
	}
}

二、服務端代碼編程

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[] head = new byte[4];// 先讀取4個字節消息頭
			while (is.read(head) != -1) {
				i++;
				int messageLenth = byteArrayToInt(head);
				byte message[] = new byte[messageLenth];
				is.read(message);// 讀取消息體
				System.out.println(new String(message));
			}
			System.out.println("總數讀取次數" + i);
			is.close();
			socket.close();
		}
	}

	public static int byteArrayToInt(byte[] b) {
		return b[3] & 0xFF | (b[2] & 0xFF) << 8 | (b[1] & 0xFF) << 16 | (b[0] & 0xFF) << 24;
	}
}

 三、運行結果數組


     這樣就實現一個報文一個報文的讀取了,基於這種實現也能夠解決RPC框架中的粘包拆包問題。網絡

3、問題
    Java支持更高效的IO方式Nio,那麼也有一些高效Nio框架,如netty、mina,這些框架極大的提升了程序員網絡編程的效率,那麼這些框架提供哪些方法去解決拆包粘包問題呢? 請關注下一篇博文《TCP粘包拆包三》
 框架

快樂源於分享。socket

   此博客乃做者原創, 轉載請註明出處   編碼

相關文章
相關標籤/搜索