为什么 Java writeBytes 方法在第一个 TCP 数据包中只发送一个字节而 write 方法不发送?
Why does Java writeBytes method send only one byte in first TCP packet and write method does not?
我在 java 中开发了一个简单的客户端(我使用 Windows 7 机器)来与服务器通信。问题是服务器从来不理解我的请求。所以我分析了与 Wireshark 的通信并注意到第一个 TCP 数据包中只发送一个字节,其余字节在另一个数据包中发送 40 毫秒后。
事实上,我们是用二进制帧来通信的,所以所有的帧都必须以帧的总长度为2字节开始。所以服务器永远不会理解我是正常的。我所有的帧都不会超过 10 个字节,所以这是一个微不足道的数据量。我知道 TCP 数据包可以被分割,但对我来说,只分割一个字节后的一个小帧是没有意义的。
经过几个小时的研究失败后,我随便尝试使用 write 方法而不是 writeBytes 方法以其他方式发送字节。现在我只在一个 TCP 数据包中发送所有数据并且通信正常,但我从未找到解释。如果有人知道,我会很乐意学习。
这是我的代码:
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();
}
}
}
Java 和 TCP 都对此不作任何保证。 TCP 可以按照它喜欢的任何方式对数据进行分段,并且您无需依赖连续传送的任何两个字节。这里的问题确实是在阅读端,做出了错误的假设。
In fact, we communicate with binary frames
事实上,您是通过字节流协议进行通信的。没有框架,没有消息边界,什么都没有。
但是,如果你想对此进行更多控制,你应该在 DataOutputStream
和套接字输出流之间使用 BufferedOutputStream
,在接收端同样使用 BufferedInputStream
.当您希望发送数据时刷新流,通常是在下一次读取之前。
我在 java 中开发了一个简单的客户端(我使用 Windows 7 机器)来与服务器通信。问题是服务器从来不理解我的请求。所以我分析了与 Wireshark 的通信并注意到第一个 TCP 数据包中只发送一个字节,其余字节在另一个数据包中发送 40 毫秒后。
事实上,我们是用二进制帧来通信的,所以所有的帧都必须以帧的总长度为2字节开始。所以服务器永远不会理解我是正常的。我所有的帧都不会超过 10 个字节,所以这是一个微不足道的数据量。我知道 TCP 数据包可以被分割,但对我来说,只分割一个字节后的一个小帧是没有意义的。
经过几个小时的研究失败后,我随便尝试使用 write 方法而不是 writeBytes 方法以其他方式发送字节。现在我只在一个 TCP 数据包中发送所有数据并且通信正常,但我从未找到解释。如果有人知道,我会很乐意学习。
这是我的代码:
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();
}
}
}
Java 和 TCP 都对此不作任何保证。 TCP 可以按照它喜欢的任何方式对数据进行分段,并且您无需依赖连续传送的任何两个字节。这里的问题确实是在阅读端,做出了错误的假设。
In fact, we communicate with binary frames
事实上,您是通过字节流协议进行通信的。没有框架,没有消息边界,什么都没有。
但是,如果你想对此进行更多控制,你应该在 DataOutputStream
和套接字输出流之间使用 BufferedOutputStream
,在接收端同样使用 BufferedInputStream
.当您希望发送数据时刷新流,通常是在下一次读取之前。