我在java中开发了一个简单的客户端(我使用Windows 7机器)与服务器进行通信。问题是服务器永远不理解我的请求。所以我分析了与Wireshark的通信,并注意到在第一个TCP数据包中只发送一个字节,剩余字节在另一个数据包中发送后40ms。
实际上,我们使用二进制帧进行通信,因此所有帧必须以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();
}
}
}
答案 0 :(得分:0)
Java和TCP都不对此做出任何保证。 TCP可以按照自己喜欢的方式对数据进行分段,并且您无需依赖连续传输的任何两个字节。这里的问题实际上是在阅读结束时,这会产生错误的假设。
实际上,我们使用二进制帧进行通信
实际上,您正在通过字节流协议进行通信。没有帧,没有消息边界,没有。
但是,如果您想要对此进行更多控制,则应在BufferedOutputStream
和套接字输出流之间使用DataOutputStream
,并在接收端使用BufferedInputStream
。当您希望发送数据时,通常在下次读取之前刷新流。