I transfer data from server to client via SocketChannel . The buffer size is 10kbyte = 10240 bytes. After getting the ByteBuffer I get a string from it, translate the string into a JSONObject and then I process the data. So the fact is that ByteBuffer often comes beaten and cannot be converted to JSONObject, although there are no errors at the time of writing / reading from the channel. How to transfer data, respecting their integrity? I was thinking of putting a checksum into the packet, but this would require additional computational resources. Tell me how to be in this situation.

And so, the reading code:

 ByteBuffer buffer = ByteBuffer.allocate(1024); public String readLine() { StringBuilder sb = new StringBuilder(); int k; do { buffer.clear(); k = socketChannel.read(buffer); buffer.flip(); CharBuffer charBuff = charset.decode(buffer); for(int i=0; i<charBuff.limit(); i++) sb.append(charBuff.get()); } while(k == 1024); return sb.toString().trim(); } 

Record Code:

 public void writeLine(String string) { socketChannel.write(charset.encode(string)); } 
  • 2
    @ Ruslan Molchanov, what exactly does "broken" mean? Most likely the data is larger than the buffer size or only part of it has arrived, and the rest will be transferred later. The data must be read in a loop until they run out and transfer everything into a JSONObject. How to determine the logical end of a chunk of data for a JSONObject is the task of your application protocol. - avp
  • @avp "Broken" means that any character may be missing, which is critical in this case. And if you re-request the data, they can come in normal form. Now I will try to implement data acquisition in a cycle - ruslanys
  • @ Ruslan Molchanov, now I can see. while (k> 0); // not 1024 I think the problem is this. Or do you always send data with a multiple of 1024? By the way, in this case you will complete the cycle on closing the socket with the sending side. If you need to transfer several Json for one connection, then either send the separator code (say 0x01) and analyze it in the for loop for append , or transfer its length in bytes to Json. - avp
  • @avp if I do while (k> 0), then sc.read (...) will block the stream when the data runs out - ruslanys
  • one
    @avp Thank you very much !!!!!!!!!!!!!!!!!! Made!!! only instead of 0x01, took the sickle and hammer symbol ((char) 9773) Now the code looks like this: do {buffer.clear (); sc.read (buffer); buffer.flip (); if (buffer.limit () == 0) return null; CharBuffer charBuff = cd.decode (buffer); for (int i = 0; i <charBuff.limit (); i ++) {char ch = charBuff.get (); if (ch == (char) 9773) finish = true; else sb.append (ch); }} while (! finish); - ruslanys

1 answer 1

This is an approximate translation from the description of how Stream-based Transport works.

In a transport-based stream, such as TCP / IP, the received data is written to the socket's receive buffer. Unfortunately, the transport-based stream buffer is not a packet queue; it is a byte queue. This means that even if you send two messages as two independent packets, the operating system will not treat them as two messages, it simply perceives them as a set of bytes. Thus, there is no guarantee that what you are reading is exactly what your remote node sent. For example, suppose the TCP / IP stack of the operating system received three packets:

| ABC | DEF | GHI |

In this regard, a common property of the flow based on the protocol, there is a high probability of reading them in the following fragmented form in your application:

| AB | CDEFG | H | I |

Thus, the receiving part, whether on the server side or on the client side, must defragment the data received in one or more packets, which can be easily understood by the application logic.

Usually, in order to understand when the bytes of a single packet have ended, they insert a "terminating packet character" (it is strictly conditional and determined by you), for example, 0x01. Sometimes in the first bytes of a packet, they encrypt its length and read as much as indicated.

  • one
    Your 1 sent packet may turn into two on the recipient side and you will not be able to influence it. How far is the client from the server? Usually packets begin to break apart when traffic increases. - sonniy
  • one
    if you use TCP, then data cannot be lost (except in rare cases, due to errors in the implementation of drivers). They either come or not. Show the code that reads the data. There is a 99.9% error. - KoVadim
  • one
    @Ruslan Molchanov try to convert the received data into a string, and not into JSONObject. You should get something like: {"age": 29, "messages": "msg"} Maybe you will see what is missing. - sonniy
  • @ Ruslan Molchanov, but show me how you send the data. Maybe immediately what good we will tell. - avp
  • one
    That's why answer my question above - is the size of the data transmitted or not? or how you will determine the end of the data (maybe after receiving the packet, the server will close the connection). If json packets are transmitted one by one, you will have to integrate the parser. - KoVadim