【硬件问题】关于tcp与buffer
发布于 2 年前 作者 Lanseria 2067 次浏览 来自 问答

是这样的,因为要做数据的联调,所以必须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) 
8 回复

有木有人 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的重传机制在这种情况也不能生效)

回到顶部