简体   繁体   English

TCP如何用Java发送/接收实时大数据包?

[英]TCP how to send/receive real-time large packets in Java?

I have this TCP server running Because UDP server was able to accept large packets but ISP blocks my UDP packets even i have Public IP and Static services. 我正在运行此TCP服务器,因为UDP服务器可以接受大数据包,但是ISP阻止了我的UDP数据包,即使我有公共IP和静态服务也是如此。 But now decided to change it to TCP but i have a large stack now to replace with UDP to TCP. 但是现在决定将其更改为TCP,但是我现在有一个很大的堆栈可以替换为UDP到TCP。

Here is the server which is running but it does not at once receive a large packet, how can i increase it to unlimited or maximum size or etc? 这是正在运行的服务器,但是它不会立即收到一个大数据包,我如何将其增加到无限制或最大大小等?

1) Is there any way with this? 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) Is there any way with this? 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);
}

None is allowing me to handle large so that i can switch from UDP to TCP. 没有人可以让我处理很多事情,以便可以从UDP切换到TCP。 Any ideas!! 有任何想法吗!!

TCP and UDP are different. TCP和UDP不同。 TCP is not a packet-based protocol, it is a stream based protocol. TCP不是基于数据包的协议,而是基于流的协议。 Your data will arrive in order, and un-corrupted, but it will not necessarily all arrive at once. 您的数据将按顺序到达且未损坏,但不一定会立即全部到达。

What you should do is prefix each set 'packet' with a length. 您应该做的是在每个集合“数据包”前面加上一个长度。 When you receive data, first read the length value, and then continue reading chunks from the socket until you have the amount of data required. 接收数据时,请先读取长度值,然后继续从套接字读取块,直到获得所需的数据量为止。

You shouldn't care how TCP splits your messages into packets and how many times you must read to get a full message. 您不必关心TCP如何将消息拆分为数据包,以及必须阅读多少次才能获得完整的消息。 Just read until the end of the message has been reached, and then return all the bytes of the message. 只需读取直到到达消息末尾,然后返回消息的所有字节即可。

Knowing when the message has been read completely depends on your protocol. 知道何时完全读取消息取决于您的协议。 You could choose to send only one message per connection, or you could send the length of the message before the message, or use some marker byte. 您可以选择每个连接仅发送一条消息,或者可以在消息之前发送消息的长度,或者使用一些标记字节。

Note that you shouldn't use new String(byte[]) without specifying an encoding (and use the same when calling String.getBytes() ), especially if you transfer from one machine to another, since both machines could have a different default encoding. 请注意,不要在未指定编码的情况下使用new String(byte[]) (并且在调用String.getBytes()时使用相同的编码),尤其是当您从一台计算机传输到另一台计算机时,因为两台计算机的默认设置可能不同编码。

The trouble you're having is how InputStreams work. 您遇到的麻烦是InputStreams的工作方式。 When you call read(buf,offset,length) it doesn't always read length bytes everytime. 当您调用read(buf,offset,length)时,它并不总是每次都读取长度字节。 It simply reads what is available() on the InputStream, and returns the number of bytes it read. 它只是读取InputStream上的available(),并返回读取的字节数。 So you need to continue to call read until you've actually read length bytes. 因此,您需要继续调用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.

You can also look at using DataInputStream.readFully() by wrapping your 您还可以通过包装您的代码来查看使用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 http://docs.oracle.com/javase/6/docs/api/java/io/DataInputStream.html

But if you're really just after a String you should do this: 但是,如果您真的只是在使用String,则应该这样做:

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

Same rules for read( char[], offset, length ) as read( byte[], offset, length ) read(char [],offset,length)的规则与read(byte [],offset,length)相同

A TCP is a stream of bytes you can get a portion of, one or more messages is a single read. TCP是可以获取一部分字节流,一个或多个消息是一次读取。 With UDP packets of more than 532 bytes, the packet can be broken up, so you have the same potential problem. 如果UDP数据包超过532个字节,则该数据包可能会被分解,因此您也有同样的潜在问题。

A simple way to encode message is to send the length first. 编码消息的一种简单方法是先发送长度。

 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();
 }

read/write UTF sends the length first and followed by the content 读/写UTF首先发送长度,然后发送内容

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM