java 使用 TCP 连接获取字节数组
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11588078/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Getting byte arrays using TCP connections
提问by Dao Lam
I was using UDP
to send/receive data but I now want to switch to TCP
to avoid packet loss.
我曾经UDP
用来发送/接收数据,但我现在想切换到TCP
以避免丢包。
I've read several tutorials on TCP
and noticed that instead of using DatagramPacket like UDP
, TCP
uses InputStream/OutputStream.
我读过几个教程TCP
和发现,而不是使用像DatagramPacket类UDP
,TCP
使用的InputStream / OutputStream中。
How do we get the byte[] from DataInputStream, something that's similar to this:
我们如何从 DataInputStream 中获取 byte[],类似于以下内容:
byte[] receiveData = new byte[64000];
DatagramPacket receivePacket = new DatagramPacket(receiveData,receiveData.length);
receiveData=receivePacket.getData();
回答by jtahlborn
in order to implement a message based protocol over a socket (stream), you basically want to come up with some message format, then read/write that on either end of the connection. a very simple format is to write the length of the message as a 4 byte int, then send the message bytes (then flush the stream). on the receiving end, read a 4 byte int, then read exactly that many following bytes(be careful that you limit your read method call or you may accidentally read part of the next message).
为了通过套接字(流)实现基于消息的协议,您基本上想要提出某种消息格式,然后在连接的任一端读取/写入该格式。一个非常简单的格式是将消息的长度写为一个 4 字节的 int,然后发送消息字节(然后刷新流)。在接收端,读取一个 4 字节的 int,然后准确读取接下来的多个字节(注意限制你的 read 方法调用,否则你可能会不小心读取下一条消息的一部分)。
public void writeMessage(DataOutputStream dout, byte[] msg, int msgLen) {
dout.writeInt(msgLen);
dout.write(msg, 0, msgLen);
dout.flush();
}
public byte[] readMessage(DataInputStream din) {
int msgLen = din.readInt();
byte[] msg = new byte[msgLen];
din.readFully(msg);
return msg;
}
回答by Haozhun
The answer has 2 parts. Dealing with 2 separate problems your questions is related to.
答案有两部分。处理与您的问题相关的 2 个独立问题。
1. Network facts
1. 网络事实
TCP is inherently stream based. i.e. Sending byte[1000] first and then byte[1200], is indistinguishable from sending byte[2200] once. What is actually send over the network can very likely be 2 packets, first being a packet with 1400 bytes and the second being 800, or 1401 and 799, and can vary each time. The receiver has no way to know the sender actually sent 1000 bytes first, and then sent 1200 bytes. This is by design in network. Java has nothing to do with this fact. And you can do nothing with it.
TCP 本质上是基于流的。即先发送字节[1000]然后发送字节[1200],与发送字节[2200]一次没有区别。实际通过网络发送的数据很可能是 2 个数据包,第一个是 1400 字节的数据包,第二个是 800 或 1401 和 799,并且每次都可能有所不同。接收方无法知道发送方实际先发送了 1000 个字节,然后发送了 1200 个字节。这是在网络中设计的。Java 与这个事实无关。你不能用它做任何事情。
2. Java implementation
2. Java实现
On the sender side. First, you need OutputStream os = tcpsocket.getOutputStream();
. And then, each time, you need os.write(byteArray)
. On The receiver side, you need InputStream is = tcpsocket.getInputStream();
. And then, each time, you need is.read(byteArray)
. Note that on the receiver side, how much of the byteArray
is actually filled will be returned. It may be any number between 1 and the capacity of the byteArray
, and is irrelevant to how the sender actually sent it.
在发送方。首先,您需要OutputStream os = tcpsocket.getOutputStream();
. 然后,每次,您都需要os.write(byteArray)
. 在接收方,您需要InputStream is = tcpsocket.getInputStream();
. 然后,每次,您都需要is.read(byteArray)
. 请注意,在接收方,byteArray
将返回实际填充的数量。它可以是 1 和 的容量之间的任何数字byteArray
,并且与发件人实际发送它的方式无关。
To ease the task, you may use DataInputStream is = new DataInputStream(tcpsocket.getInputStream());
at the beginning, and use is.readFully(byteArray)
each time you need to read something. This way, it can be guaranteed that byteArray
will always be filled.
为了减轻任务,您可以DataInputStream is = new DataInputStream(tcpsocket.getInputStream());
在开始时使用,并在is.readFully(byteArray)
每次需要阅读某些内容时使用。这样,可以保证byteArray
总是被填满。
But you can never know how many bytes you should receive if the actual length is variable unless you add some extra information. For example, send the length first, using 4 bytes. How you will actually do this is usually closely related to your actual use case. And it's up to you
但是,除非您添加一些额外信息,否则您永远无法知道如果实际长度是可变的,您应该接收多少字节。比如先发送长度,使用4个字节。您将如何实际执行此操作通常与您的实际用例密切相关。这取决于你