简体   繁体   中英

Why does Java writeBytes method send only one byte in first TCP packet and write method does not?

I have developing a simple client in java (I use a Windows 7 machine) to communicate with a server. The problem was that the server never understood my request. So I have analysed the communication with Wireshark and have noticed that only one byte is send in a first TCP packet, and 40ms after the remaining bytes are send in a other packet.

In fact, we communicate with binary frames, so all the frames must begin with the total length of the frame on 2 bytes. So it is normal that the server will never understand me. All my frames never exceed 10 bytes, so it's a insignificant amount of data. I know that TCP packets can be segmented, but for me it has no sense to segment a tiny frame after only one byte.

After unsuccessful hours of research, I tried casually to send bytes in a other way using write method instead of writeBytes method. Now I send all the data in only one TCP packet and the communication works fine, but I have never find the explanation. If someone knows, I will be happy to learn it.

Here is my code :

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;

public class Client {

public static void main(String argv[]) {

    try {
        Socket socket = new Socket();
        socket.connect(new InetSocketAddress("10.2.1.1", 1003), 1000);
        DataOutputStream outToServer = new DataOutputStream(socket.getOutputStream());
        DataInputStream inFromServer = new DataInputStream(socket.getInputStream());

        // Hexadecimal frame to send to server
        String hexFrame = "0004FF9D3175";

        // Build bytes frame
        String bytesFrame = "";
        for (int i=0; i<hexFrame.length()/2; i++) {
            bytesFrame += (char) Integer.parseInt(hexFrame.substring(i*2, (i+1)*2), 16);
        }

        // This generates 2 TCP packets
        // outToServer.writeBytes(bytesFrame);
        // This generates only 1 TCP packet
        outToServer.write(bytesFrame.getBytes());

        // Read answer from server
        hexFrame = "";
        short frame_length = inFromServer.readShort();
        for (int i=0; i<frame_length; i++) {
            hexFrame += String.format("%2s", Integer.toHexString(inFromServer.readUnsignedByte())).replace(" ", "0");
        }

        System.out.println("Receive : " + hexFrame);

        socket.close();
    } catch (IOException e) {
        e.printStackTrace();
    }

}

}

Neither Java nor TCP makes any guarantees about this. TCP can segment the data any way it likes, and you have no business relying on any two bytes being delivered consecutively. The problem here is really at the reading end, that makes incorrect assumptions.

In fact, we communicate with binary frames

In fact you are communicating over a byte-stream protocol. No frames, no message boundaries, nothing.

However, if you want a little more control over this you should use a BufferedOutputStream between the DataOutputStream and the socket output stream, and similarly a BufferedInputStream at the receiving end. Flush the stream when you want the data to be sent, typically just before the next read.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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