使用TCP连接获取字节数组

我使用UDP发送/接收数据但我现在想切换到TCP以避免丢包。

我已经阅读了几篇关于TCP教程,并注意到TCP不使用像UDP这样的DatagramPacket,而是使用InputStream / OutputStream。

我们如何从DataInputStream获取byte [],这与此类似:

 byte[] receiveData = new byte[64000]; DatagramPacket receivePacket = new DatagramPacket(receiveData,receiveData.length); receiveData=receivePacket.getData(); 

答案有两部分。 处理与您的问题相关的2个独立问题。

1 。 网络事实

TCP本质上是基于流的。 即首先发送字节[1000]然后发送字节[1200],与发送字节[2200]一次无法区分。 通过网络实际发送的内容很可能是2个数据包,首先是1400字节的数据包,第二个数据包是800,或1401和799,并且每次都可以变化。 接收方无法知道发送方实际上先发送了1000个字节,然后发送了1200个字节。 这是网络设计。 Java与这个事实无关。 你无能为力。

2 。 Java实现

在发件人方面。 首先,您需要OutputStream os = tcpsocket.getOutputStream(); 。 然后,每次都需要os.write(byteArray) 。 在接收方,你需要InputStream is = tcpsocket.getInputStream(); 。 然后,每次都需要is.read(byteArray) 。 请注意,在接收方,将返回实际填充多少byteArray 。 它可以是1和byteArray容量之间的任何数字,并且与发送方实际发送它的方式无关。

为了简化任务,您可以使用DataInputStream is = new DataInputStream(tcpsocket.getInputStream()); 在开始时,每次需要读取内容时都使用is.readFully(byteArray) 。 这样,可以保证byteArray将始终被填充。

但是,如果实际长度是可变的,除非您添加一些额外信息,否则您永远不会知道应该接收多少字节。 例如,首先使用4个字节发送长度。 您将如何实际执行此操作通常与您的实际用例密切相关。 这取决于你

为了在套接字(流)上实现基于消息的协议,你基本上想要提出一些消息格式,然后在连接的任何一端读/写。 一种非常简单的格式是将消息的长度写为4字节的int,然后发送消息字节(然后刷新流)。 在接收端,读取一个4字节的int,然后准确读取后面的多个字节 (注意你限制你的读取方法调用,否则你可能会意外地读取下一条消息的一部分)。

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