簡體   English   中英

Java通過TCP Socket分別發送數據

[英]Java send data over TCP Socket seperately

我想在 Java 中使用 tcp 套接字分別發送多個數據包。 這是我的代碼。

try {
    DataOutputStream out = new DataOutputStream(socket.getOutputStream());
    String[] array = new String[4];
    array[0] = "stack";
    array[1] = "over";
    array[2] = "flow";
    array[3] = "coding";
    for (int i = 0; i < array.length; i++) {
        out.write(array[i].getBytes()); //send packet
    }
} catch (IOException e) {
    throw new RuntimeException(e);
}

我現在把所有數據都放在一個數據包中。 這是接收到的數據包的終端輸出:

Incoming Transmission => stackoverflowcoding

這就是我想要的:

Incoming Transmission => stack
Incoming Transmission => over
Incoming Transmission => flow
Incoming Transmission => coding 

如何分別接收 4 個數據包的數據?

我為什么要這個? 因為在我的客戶中有一個監聽即將到來的 tcp 包的事件。 必須為數組的每個元素分別觸發此事件。

TCP 在邏輯上表示一個連續的流,類似於一個文件。 將其視為一個連續的字節序列,直到某個時間點關閉並且流結束。 但是這些字節中的任何兩個之間都沒有明確的界限。 有時您可能不得不等待獲取更多字節,但沒有內在的方法可以判斷這是因為對方停止發送還是你們兩個之間存在某種網絡問題。

雖然數據包被用作底層機制,但您不應依賴它們的分離,因為理論上它們可以沿途拆分和合並(實際上它們大多只是拆分而很少合並)。

通常的解決方案是在 TCP 之上使用某種協議來清楚地標記您感興趣的不同塊。最簡單的此類協議將簡單地從發送下一個塊將長的字節數開始,然后是任何數據是。

或者,您可以切換到 UDP,它實際上是基於數據包的,並保證如果您收到某些東西,它將是來自另一端的單個數據包(盡管它不保證數據包的順序甚至它們的傳遞)。

可以通過在代碼中策略性地放置out.flush()來完成這項工作,但取決於這將使您的代碼非常脆弱。

TCP 是一個字節流,它沒有消息邊界的概念(例如,UDP 就是這樣)。 發送和讀取之間沒有一對一的關系。 發送的數據可以在網絡認為有效傳輸所需的任何數據包中加入和分段。 TCP 為您提供的唯一保證是:

  • 數據將被傳遞(除非連接關閉或丟失)
  • 數據將按照發送的順序接收

因此,要執行您的要求,您必須明確標記一個數據的結束位置和下一個數據的開始位置。 例如,通過在實際數據之前發送數據的長度,例如:

try {
    DataOutputStream out = new DataOutputStream(new BufferedOutputStream(socket.getOutputStream()));
    String[] array = new String[4];
    array[0] = "stack";
    array[1] = "over";
    array[2] = "flow";
    array[3] = "coding";
    out.writeInt(array.length);
    for (int i = 0; i < array.length; i++) {
        byte[] bytes = array[i].getBytes(StandardCharsets.UTF_8);
        out.writeInt(bytes.length);
        out.write(bytes, 0, bytes.length);
    }
    out.flush();
} catch (IOException e) {
    throw new RuntimeException(e);
}

這樣,接收者可以首先讀取一個整數以了解正在發送多少個字符串,然后運行一個循環,其中每次迭代讀取字符串長度的整數,然后讀取該字符串的字節,例如:

try {
    DataInputStream in = new DataInputStream(new BufferedInputStream(socket.getInputStream()));
    int count = in.readInt();
    for (int i = 0; i < count; i++) {
        int length = in.readInt();
        byte[] bytes = new byte[length];
        in.readFully(bytes);
        String s = new String(bytes, StandardCharsets.UTF_8);
        System.out.println("Incoming Transmission => " + s);
    }
} catch (IOException e) {
    throw new RuntimeException(e);
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM