为何Java发送数据会被拆包而用NodeJs就不会?
const net = require('net');const str = '3c3f8f6e7c8d9c1a2s3d4f6f';//此处省略大部分数据
console.log(str.length);
const buf = Buffer.allocUnsafe(4);
buf.writeInt32BE(str.length / 2);
let totalBuf = buf;
for (let i = 0; i <str.length; i += 2) {
let hex = str.substr(i, 2);
console.log('str: ' + hex);
hex = parseInt(hex, 16);
console.log('hex: ' + hex);
const temp = Buffer.allocUnsafe(1);
temp.writeInt8(hex, 0, 1, true);
totalBuf = Buffer.concat([totalBuf, temp]);
console.log(totalBuf);
}
console.log(totalBuf);
const client = net.connect(3000, '172.11.111.25', () => {
// 'connect' listener
console.log('connected to server!');
client.write(totalBuf);
});
client.on('data', (data) => {
console.log(data.toString());
client.end();
});
client.on('end', () => {
console.log('disconnected from server');
});
js代码如上所示,抓包得到:
可以看出前三条报文分别为
TCP的三次握手:SYN,对方发来的SYN + ACK,ACK
第四条报文为数据(PSU),有674个字节
第五条报文是对方发来的对第四条报文的确认
第六条是对方(Java写的系统)发来的数据,只有一个字节
第七条我方确认,第八条对方数据,三个字节,
第九条我方确认,第十条我方FIN
第十一条对方数据,830字节
第六,七,十一条组成了报文的数据组合起来才是完整的,说明发生了拆包,拆包原因不明。
以下是我用Java发送数据,同样发生了拆包:
代码如下:
public byte[] requestSend(byte[] data, boolean synRespFlag) throws Exception { try {
DataOutputStream dataout = new DataOutputStream(
this.commSock.getOutputStream());
if (data != null) {
dataout.writeInt(data.length);
dataout.write(data);
String output = new String(data);
MyLogger.getInstance().info("待发送的报文数据为:\n" + output);
}
dataout.flush();
// dataout.close();
if (synRespFlag) {
DataInputStream datain = new DataInputStream(
this.commSock.getInputStream());
int readTimeout = Integer.parseInt(GlobalConfig.getInstance()
.getResponseTimeout());
this.commSock.setSoTimeout(readTimeout);
int dataLength = datain.readInt();
MyLogger.getInstance().info("报文长度为:" + dataLength);
byte[] recvBuffer = new byte[dataLength];
datain.read(recvBuffer, 0, dataLength);
String input = new String(recvBuffer);
MyLogger.getInstance().info("接收报文数据:\n" + input);
datain.close();
dataout.close();
return recvBuffer;
}
return null;
}
catch (Exception e) {
MyLogger.getInstance().error(
"发送请求数据出错:" + ExceptionInfo.getInfo(e));
throw e;
}
}
抓包:
数据被分散到第四和第六条报文,分别为1字节和673字节。
回答:
用TCP发送和接收数据时,一定要做好两个假设:
一段数据可能在任意位置被拆开;
前后两段数据可能在会被粘在一起。
这两种情况可以认为是随机发生的。
拆和粘不一定由语言、操作系统引起,也可能是由路由器引起的。
所以并不能保证NodeJS一定不会拆,也不能保证Java一定会拆,只是可能NodeJS和Java在操作系统层TCP调用时,实现机制不同,但开发者应该无视这种不同,严格按照前面两条假设来处理数据。
UPDATE
仔细看了问题中的Java代码,发现用了DataOutputStream,这个很坑的,看下源码就知道了,它对writeInt是分4次write的。
有两种方式可以改善发送效率:
再用BufferedOutputStream包一层;
不要用DataOutputStream,而是自己拼装byte[],一次性用SocketOutputStream直接发掉,在这个例子中可以用
byte[4 + data.length]
。
以上是 为何Java发送数据会被拆包而用NodeJs就不会? 的全部内容, 来源链接: utcz.com/p/178666.html