I was using UDP
to send/receive data but I now want to switch to TCP
to avoid packet loss.
I've read several tutorials on TCP
and noticed that instead of using DatagramPacket like UDP
, TCP
uses InputStream/OutputStream.
How do we get the byte[] from DataInputStream, something that's similar to this:
byte[] receiveData = new byte[64000];
DatagramPacket receivePacket = new DatagramPacket(receiveData,receiveData.length);
receiveData=receivePacket.getData();
The answer has 2 parts. Dealing with 2 separate problems your questions is related to.
1. Network facts
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.
2. Java implementation
On the sender side. First, you need
OutputStream os = tcpsocket.getOutputStream();
. And then, each time, you needos.write(byteArray)
. On The receiver side, you needInputStream is = tcpsocket.getInputStream();
. And then, each time, you needis.read(byteArray)
. Note that on the receiver side, how much of thebyteArray
is actually filled will be returned. It may be any number between 1 and the capacity of thebyteArray
, and is irrelevant to how the sender actually sent it.To ease the task, you may use
DataInputStream is = new DataInputStream(tcpsocket.getInputStream());
at the beginning, and useis.readFully(byteArray)
each time you need to read something. This way, it can be guaranteed thatbyteArray
will always be filled.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
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).