2012-06-20 65 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等

在每种情况下,必须在一个循环中读取在接收器中,直到您收到完整的消息。

相关问题