【问题标题】:TCP how to send/receive real-time large packets in Java?TCP如何在Java中发送/接收实时大数据包?
【发布时间】:2012-01-06 15:23:01
【问题描述】:

我有这个 TCP 服务器正在运行,因为 UDP 服务器能够接受大数据包,但即使我有公共 IP 和静态服务,ISP 也会阻止我的 UDP 数据包。但现在决定将其更改为 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。有什么想法!!

【问题讨论】:

  • 您是否遇到了一些特定的错误?
  • 如果你想要一个面向消息的协议,它会为你处理消息边界,也许你应该寻找 SCTP...

标签: java linux networking windows-7


【解决方案1】:

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

您应该做的是在每个集合的“数据包”前面加上一个长度。当你接收到数据时,首先读取长度值,然后继续从套接字中读取块,直到你拥有所需的数据量。

【讨论】:

【解决方案2】:

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

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

请注意,您不应在未指定编码的情况下使用new String(byte[])(在调用String.getBytes() 时使用相同的编码),尤其是当您从一台机器转移到另一台机器时,因为两台机器可能具有不同的默认编码。

【讨论】:

    【解决方案3】:

    您遇到的问题是 InputStreams 的工作方式。当您调用 read(buf,offset,length) 时,它并不总是每次都读取长度字节。它只是读取 InputStream 上的可用内容(),并返回它读取的字节数。所以你需要继续调用 read 直到你真正读取了 length 个字节。

    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) 的规则相同

    【讨论】:

    • 在没有使用长度的情况下,我编写了一个协议,并在其中发送“END”信号。
    【解决方案4】:

    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 先发送长度,后发送内容

    【讨论】:

      猜你喜欢
      • 2011-09-13
      • 2013-07-04
      • 2012-04-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-11-12
      • 2020-09-03
      • 2021-12-14
      相关资源
      最近更新 更多