是这样的,因为要做数据的联调,所以必须tcp之类的通信 可是毕竟硬件传过来的事hex 也就是二进制的数据, 类似下面这中数据,我本想用构造去做,不过因为有些长度是会变的,所以很难处理,如果要按硬件一次一次轮询的去判断,switch实在太多了,求大佬的经验之谈!
53 54 41 54 00 0F 01 00 00 00 00 00 00 BB 01 AA 09 BB 01 00 01 00 00 00 00 00 01 0E CC 33 45 4E 44
53 54 41 54 (STAT)
00 0F (长度)\\\\\\\\\\\\\\\\\\\\\
01 (cmd)
00 00 00 00 00 00 (网关ID)
BB
01 (模块数量)
AA (头)\\\\\\\\\\\\\\\\\\\15
09 (长度)16
BB 17
01 00 (设备类型) 18
01 00 00 00 00 00 (设备ID)20
01 (具体的数据)26
0E (子crc)27
CC (模块数据结束)28
33 CRC(总)
45 4E 44 (END)
有木有人 From Noder
首先要自定义协议,解决粘包与分包问题,不然,收到的数据无法解析的
弱弱的问一下,这种自定义TCP通信的话,是不是最起码要有一个长度的说明,比如HTTP中的Content-length,这样客户端这边才知道用多大的Buffer去装
协议头 协议长度 协议体 CRC 除了协议体其他是固定的
使用protobuf 塞到buffer里,然后自己写转换。需要处理粘包,5年前我第一个项目就是这么做的。5年前的代码了,你凑活凑活看吧,
function GameMain(aPort,aCallback){ var mCenterSocket = mNet.createConnection(aPort,‘127.0.0.1’); /** 连接成功 */ mCenterSocket.on(‘connect’, function() { mProcessingLogic.SetSocket(mCenterSocket); mProcessingLogic.EfficacySocket(); mLogger.ConsoleLog("Connected to GateServer at port: " + aPort); });
var tBuffer = new mPackageSystem.exPackag(onReceivePackData);
/** 接收数据的方法 */
mCenterSocket.on('data', function(data) {
tBuffer.putData(data);
});
/** 连接断开 */
mCenterSocket.on('close', function(data) {
mLogger.ConsoleLog('GateServer connection closed');
setTimeout(function(){
mLogger.ConsoleLog('GateServer reconnecting...');
mCenterSocket.connect(aPort,'127.0.0.1');
},3000);
});
/** 连接的异常 */
mCenterSocket.on('error', function(error) {
mLogger.ConsoleLog('GateServer connection error');
});
/** 一个完整的包 */
function onReceivePackData(aBuffer){
aBuffer=new Buffer(aBuffer);
var tObj=mCommon.getServerBag(aBuffer);
if(tObj!=null)
{
mLogger.ConsoleLog("===== UID:" + tObj.Obj.uid + " " + tObj.MessageName);
mRouter.RouteSocket(tObj);
}
else
{
mLogger.ConsoleLog("消息验证失败");
}
}
aCallback(null, null);
}
------------------------------------mPackageSystem.js-------------------------------------------- function exPackag(aCallback) { this.mBuffer = new Array();// 缓冲容器 this.mBuffer_len = 0;// 协议长度 this.mData_len_Median = 2;// 协议的长度所占的位数 this.mCallback = aCallback;// 回调函数 }
exPackag.prototype.putData = function(aData) { //mLogger.ConsoleLog("PS putData: " + aData.length); if (this.mBuffer_len == 0) { if (aData.length < this.mData_len_Median) { mLogger.SetDebug(‘包头不全直接忽略’); return; } else { this.mBuffer_len = getIntToByte16(aData) + this.mData_len_Median; } }
for (var index = 0; index < aData.length; index++) {
this.mBuffer.push(aData[index]);
}
if (this.mBuffer_len == -1) {
this.mBuffer_len = getIntToByte16(this.mBuffer) + this.mData_len_Median;
}
while (this.mBuffer_len > 0) {
/** 如果缓存中的长度刚好是一个包的长度 */
if (this.mBuffer.length == this.mBuffer_len) {
//mLogger.ConsoleLog('刚好是一个包');
this.mCallback(this.mBuffer);
this.mBuffer = null;
this.mBuffer = new Array();
this.mBuffer_len = 0;
return;
}
/** 如果缓存中的长度大于一个包的长度 */
else if (this.mBuffer.length > this.mBuffer_len) {
//mLogger.ConsoleLog('大于一个包,包头长度:' + this.mBuffer_len + ',实际长度:' + this.mBuffer.length);
/** 先获取一个完整的包 */
var tBuffer = this.mBuffer.splice(0, this.mBuffer_len);
this.mCallback(tBuffer);
tBuffer = null;
if (this.mBuffer.length >= this.mData_len_Median) {
this.mBuffer_len = getIntToByte16(this.mBuffer) + this.mData_len_Median;
} else {
this.mBuffer_len = -1;
}
} else {
/** 不满足长度 */
//mLogger.ConsoleLog('不满足长度,包头长度:' + this.mBuffer_len + ',实际长度:' + this.mBuffer.length);
this.mBuffer_len = -1;
return;
}
}
};
function getIntToByte16(aRecv) { var targets = (aRecv[0] & 0xff) | ((aRecv[1] << 8) & 0xff00); return targets; }
exports.exPackag = exPackag;
-----------------------------------------------------压缩部分----------------------------------------- //aData是protobuf结构 function serializedServerBag(aData) { aData=JSON.stringify(aData); aData=new Buffer(aData); var tMessageDataLen=aData.length; var tValue=getByteToInt16(tMessageDataLen); var tBuf=Array(); tBuf=tBuf.concat(tValue); for(var index=0; index<aData.length; index++) { tBuf.push(aData[index]); } return tBuf; }
谢谢,我会仔细看的
@beiyio 您好,有个问题想请教下还望您帮忙解答:当解到包后,业务需要对某些包进行处理,是比较耗时的for循环,会使程序阻塞,此时有可能使tcp的传输收到阻塞,而丢失部分数据,要防止这种问题,请问有什么好的办法吗?(发送端的缓存极小,通常阻塞500ms就已经撑满发送端的TCP缓存区,即出现丢包,所以,TCP的重传机制在这种情况也不能生效)
@Lanseria 您好,有个问题想请教下还望您帮忙解答:当解到包后,业务需要对某些包进行处理,是比较耗时的for循环,会使程序阻塞,此时有可能使tcp的传输收到阻塞,而丢失部分数据,要防止这种问题,请问有什么好的办法吗?(发送端的缓存极小,通常阻塞500ms就已经撑满发送端的TCP缓存区,即出现丢包,所以,TCP的重传机制在这种情况也不能生效)