TCP如何在Java中发送/接收实时大包?

时间:2012-01-06 15:23:02

标签: java linux networking windows-7

我有这个TCP服务器运行因为UDP服务器能够接受大数据包但ISP阻止我的UDP数据包,即使我有公共IP和静态服务。但现在决定将其更改为TCP,但我现在有一个大堆栈用UDP替换为TCP。

这是正在运行但没有立即收到大包的服务器,如何将其增加到无限制或最大尺寸等?

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。任何想法!!

4 个答案:

答案 0 :(得分:2)

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

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

答案 1 :(得分:1)

您不应该关心TCP如何将邮件拆分为数据包以及您必须阅读多少次才能获得完整的邮件。只需读取直到消息结束,然后返回消息的所有字节。

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

请注意,如果不指定编码,则不应使用new String(byte[])(并且在调用String.getBytes()时使用相同的编码),尤其是当您从一台计算机转移到另一台计算机时,因为两台计算机可能有不同的默认编码。

答案 2 :(得分: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,length)

答案 3 :(得分: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首先发送长度,然后是内容