2012-01-06 934 views
1

我有这个TCP服务器运行因为UDP服务器能够接受大数据包但ISP阻止我的UDP数据包,即使我有公共IP和静态服务。但现在决定将其更改为TCP,但现在我有一个大堆栈来替换UDP到TCP。TCP如何在Java中发送/接收实时大数据包?

这里是服务器正在运行,但它并没有立即收到一个大包,我怎么能增加到无限或最大尺寸或等?

1)有什么办法呢?

public void run() 
{ 
    while(true) 
    { 
     byte[] buf=new byte[5024]; <<< not helping!! 
     int bytes_read = 0; 
     try {         
      bytes_read = sockInput.read(buf, 0, buf.length);     
      String data = null; 
      data = new String(buf, 0, bytes_read);     
      System.out.println("[TCP]: incomeing data: " + bytes_read + " bytes, data=" +data); 
    } 
} 

2)有什么办法呢?

public TCPHandler(Socket sock) throws IOException 
{ 
    sock.setReceiveBufferSize(10*1024 +1024); //<<<<< not helping !!! 
    sock.setSendBufferSize(10*1024+1024); 
    this.sock = sock; 
    sockInput = sock.getInputStream(); 
    sockOutput = sock.getOutputStream(); 
    this.myThread = new Thread(this); 
} 

没有让我能够处理大,以便我可以从UDP切换到TCP。有任何想法吗!!

+0

你得到一些具体的错误? – cdeszaq 2012-01-06 15:25:52

+0

如果你想要一个面向消息的协议,这将为你处理消息边界,也许你应该寻找SCTP ... – lvella 2012-01-06 15:35:42

回答

1

您遇到的问题是InputStreams如何工作。当你调用read(buf,offset,length)时,它并不总是每次读取长度字节。它只是读取InputStream上的available(),并返回它读取的字节数。所以你需要继续调用read,直到你实际读取了长度字节。

int len = 0; 
int expectedLength = sockInput.readInt(); 
byte[] buf = new byte[ expectedLength ]; 
while(len != buf.length) { 
    len += sockInput.read(buf, len, buf.length); 
} 

// now you have a buffer with expectedLength data in it. 

你也可以看看使用DataInputStream.readFully()通过包裹你的

DataInputStream ds = new DataInputStream(sock.getInputStream()); 
ds.readFully(buf, 0, buf.length); 

http://docs.oracle.com/javase/6/docs/api/java/io/DataInputStream.html

但如果你只是一个字符串后,真的,你应该这样做:

Reader reader = new InputStreamReader(sockInput.getInputStream(), "UTF-8"); 

read(char [],offset,length)与read(byte [],offset,len gth)

+0

没有我使用的长度,我写了一个协议,我发送了一个“END”信号。 – YumYumYum 2012-01-07 19:20:50

2

TCP和UDP是不同的。 TCP不是基于分组的协议,而是基于流的协议。您的数据将按顺序到达,并且未被破坏,但不一定会全部到达。

你应该做的是在每个包的前面添加一个长度。当您收到数据时,首先读取长度值,然后继续从套接字读取数据块,直到获得所需的数据量。

+0

我正在使用它来获取数据https://gist.github.com/1571076,但我想念的都是。 – YumYumYum 2012-01-06 15:32:56

1

您不应该在乎TCP如何将消息分成多个数据包,以及您必须阅读多少次才能获得完整消息。只要阅读,直到到达消息的末尾,然后返回消息的所有字节。

了解消息何时完全读取取决于您的协议。您可以选择每个连接只发送一条消息,也可以在消息前发送消息的长度,或者使用某些标记字节。

注意,你不应该没有指定的编码使用new String(byte[])(和调用String.getBytes()时所使用的相同),特别是如果你从一台机器转移到另一个,因为两台机器可以有一个不同的默认编码。

1

TCP是可以获得一部分字节流,一个或多个消息是单个读取。 使用超过532字节的UDP数据包时,数据包可能被分解,因此您有相同的潜在问题。

编码消息的一种简单方法是首先发送长度。

final DataOutputStream out = new DataOutputStream(new BufferedOutputStream(socket.getOutputStream())); 
final DataInputStream in = new DataInputStream(new BufferedInputStream(socket.getInputStream())); 

public void writeMessage(String text) { 
    out.writeUTF(text); 
} 

public String readMessage() { 
    return in.readUTF(); 
} 

读/写UTF发送长度第一,其次是内容