2012-06-20 69 views
3

在我的Java應用程序中,打開了一個Socket並正在從其InputStream中讀取數據。來自套接字的分隔數據

在最佳條件下,每個進入的數據包都會導致調用read()以返回其應用程序層數據。這是我想要得到的 - 每數據包一個'消息'。

但是,數據可能會根據getReceiveBufferSize()返回的值在套接字中緩衝。如果發生這種情況並從中讀取數據流,則可能會有來自多個數據包的數據位於此處。

是否有另一種方法從單個數據包中獲取數據,或者是否違反了抽象層? 另外,是否有可能爲數據被附加到緩衝區時設置某種分隔符?或者是在平臺級別上的某些事情無法完成?

下面是一些示例代碼,以證明我在做什麼:

import java.io.InputStream; 
import java.net.Socket; 

public class Belnets { 


public Belnets() { 
    try{ 
     Socket s = new Socket("address", 23); 
     System.out.println("platform will buffer this much: "+s.getReceiveBufferSize()); 
     InputStream sin = s.getInputStream(); 
     byte[] data = new byte[1024]; 
     int c; 
     while(true){ 
      c = sin.read(data); 
      for(int i=0; i<c; i++){ 
       System.out.print((char)data[i]); 
      } 
      System.out.println("=END OF READ="); 

      //if you dont do this, read() seems to return once for each packet as this loop 
      //appears to be running fast enough to keep up with the rate of data that comes in. 
      //otherwise data gets buffered and you get multiple packets worth of data before seeing 
      //=END OF READ= 
      Thread.sleep(1000);  

     } 

    }catch(Exception e){ 
     e.printStackTrace(); 
    } 
} 



public static void main(String args[]){ 
    new Belnets(); 
} 

} 
+0

'while(true)'should' while(c!= -1)' – elias

+1

你能改變數據的發送方式嗎?如果是的話,你可以在發送的消息的末尾添加一個消息結束符dlimiter,你可以在接收數據時查找它(確保你選擇的分隔符通常不能成爲消息的一部分) – Attila

回答

5

Java的API不提供任何方式來閱讀的TCP數據包。它基於數據流,你一次無法讀取一個數據包。例如,如果要發送和接收多個消息,則需要實現應用程序級別的協議,該協議可能會在消息之間使用特定的分隔符,或者發送消息的長度,然後再發送消息正文本身。

0

while循環需要改變:

while (true) { 
    c = sin.read(data); 
    if (c < 0) 
     break; // quit if there's nothing else to read. 
    for(int i=0; i<c; i++){ 
     System.out.print((char)data[i]); 
    } 
... 
} 
0

這不是真的有可能還是一個好主意,嘗試讀取TCP數據包。 TCP是基於流的,這意味着不能保證一切都會一次發送/接收。您可能會考慮使用UDP(不太可靠,但所有內容都會一次發送),或者提出自己的分隔方案。 (一種流行的方法是發送「數據包」的長度,然後是實際數據包本身。)

2

在最佳條件下,每個進入的數據包都會導致對read()的調用,以返回其應用程序層數據。

不,這不是'最佳條件',這是純粹的運氣。 Java或底層BSD套接字API或TCP RFC沒有任何權利依賴於此行爲。 TCP是一個流媒體協議,時間段,API是字節流API,也是一段時間。

如果你想申請的消息,或者你必須自己實現這些功能分組,通過:

  1. ,前綴的長度字的每個消息。
  2. 使用更高級別的協議,諸如對象序列化,XDR等
  3. 使用一個自描述協議,諸如XML,JSON等

在每種情況下,必須在一個循環中讀取在接收器中,直到您收到完整的消息。

相關問題