tcp 收发数据demo(带粘包处理解决方案)
发布于 6 年前 作者 lvgithub 4601 次浏览 来自 分享

项目地址: https://github.com/lvgithub/stick 进入example目录,1、运行server.js 2、运行client.js即可测试demo

server

const net = require('net')
const stick_package = require('../index')

let tcp_server = net.createServer(function (socket) {
    socket.stick = new stick_package(1024).setReadIntBE('32')
    socket.on('data', function (data) {
        socket.stick.putData(data)
    })

    socket.stick.onData(function (data) {
        // 解析包头长度
        let head = new Buffer(4)
        data.copy(head, 0, 0, 4)

        // 解析数据包内容
        let body = new Buffer(head.readInt32BE())
        data.copy(body, 0, 4, head.readInt32BE())

        console.log('data length: ' + head.readInt32BE())
        console.log('body content: ' + body.toString())
    })

    socket.stick.onError(function (error) {
        console.log('stick data error:' + error)
    })

    socket.on('close', function (err) {
        console.log('client disconnected')
    })
})

tcp_server.on('error', function (err) {
    throw err
})
tcp_server.listen(8080, function () {
    console.log('tcp_server listening on 8080')
})

client

const net = require('net')

const client = net.createConnection({ port: 8080, host: '127.0.0.1' }, function () {
    let body = Buffer.from('username=123&password=1234567,qwe')

    // 写入包头
    let headBuf = new Buffer(4)
    headBuf.writeUInt32BE(body.byteLength, 0)
    console.log('data length: ' + headBuf.readInt32BE())

    // 发送包头
    client.write(headBuf)
    // 发送包内容
    client.write(body)
    console.log('data body: ' + body.toString())

})

client.on('data', function (data) {
    console.log(data.toString())
})
client.on('end', function () {
    console.log('disconnect from server')
})
6 回复

TCP挺多框架的。着几年一直用的pomelo这些都不用在处理了。 贴一个5 6年前自己写的 -----------------------------------------------------------------------package_system.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; -----------------------------------------------------------------------game_index.js------------------------------------------------------------------------------------------------- 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);

}

exports.GameMain = GameMain;

谢谢楼主,这个包很好用。给你star !

@jude90 谢谢支持,欢迎一起维护升级

回到顶部