StickNode.Js中的TCP粘包和分包解决方案!持续更新,源码地址,喜欢请点star,想订阅watch目录安装项目特性配置介绍API更新记录使用方法案例演示安装npmistickpackage项目特性:内存占用低,采用循环队列数据结构,和解包处理,队列内存用户根据数据包大小配置。高并发,目前线上业务每秒1500个数据包,每个数据包300字节,内存稳定在30M以内,单核cpu稳定在40%以内配置介绍[x]提供TCPsticky的解决方案packetprocessing[x]]默认缓冲区为512字节。当接收到的数据超过512字节时,缓冲区空间自动扩展为512的倍数[x]默认情况下,数据包长度在包头中用两个字节表示[x]默认情况下,数据以big-endian方式接收mode[x]]可以配置big-endian和small-endian读取[x]可以配置自定义包头长度[x]支持自动解包APIstick(bufferSize)=>直接处理字节型包bufferSize:setsticktohandlestickypacketcachespacestick.setReadIntBE(type)=>设置为big-endian模式<根据数据包的最大值选择合适的type>setReadIntBE(type)type:16headerlengthis2,shorttypesetReadIntBE(type)type:32packetheaderlengthis4,inttypestick.setReadIntLE=>settolittle-endianmode<根据数据包的最大值选择合适的type>setReadIntLE(type)type:16headerlengthis2,shorttypesetReadIntLE(type)type:32packetheaderlengthis4,inttypestick.putData(buffer)=>将需要处理粘包的字节流推送到stick。body中,如果不想处理包头,使用msgCenter打包,用msgCenter(options)=>可以直接发送字符串消息,基于stick封装,屏蔽stick层需要步骤自己组装和拆包头。options.bufferSize:设置用户处理粘包的缓存空间options.type:设置包头为16位或32位模式(16|32)options.bigEndian:设置big-endian和little-endian字节流模式,默认为中断模式,为false时,是小端模式(true|false)msgCenter.putMsg(msg)=>向消息中心推送一个字符串消息msgCenter.publish(msg)=>发布一条消息,返回一个打包好的buffer(包头+包体),userclent发送包时使用msgCenter.publish('123')=>//0003包长313233字符串ascii码123msgCenter.onMsgRecv(msgHandleFun)=>处理粘包处理后的消息msgHandleFun:businessMessageprocessingfunctionmsgCenter.onMsgRecv(msg=>{console.log(`recvdata:`+msg.toString())...dosomething})updaterecord:setbigendian,littleendianreceive,addsetReadIntBE,addsetReadIntLE方法支持直接发送字符串消息,自动组装header。服务器处理粘性数据包。//默认的client.js使用msgCenter.publish('...')向服务器发送消息。//下面是服务端收到的消息之后进行粘包处理constMsgCenter=require('stickpackage').msgCenterconstmsgCenter=newMsgCenter()//服务端监听分包后的消息msgCenter.onMsgRecv(data=>{console.log(`recvdata:`+data.toString())})//将tcpserver监听的字节流放入msgCentermsgCenter.putData(Buffer.from([0x00,0x02,0x31,0x32,0x00,0x04,0x31,0x32,0x33,0x34]))//=>recvdata:12//=>recvdata:1234发送二进制数据//默认client.js采用stick配置组发送amessagetotheserverinapackage//下面是服务端收到消息后的粘包处理constStick=require('stickpackage').stick;conststick=newStick(1024).setReadIntBE('16')/**包含两个数据包,10个字节,header很短,两个字节:[0x00,0x02],[0x00,0x04]*数据包1:[0x00,0x02,0x66,0x66]*数据包2:[0x00,0x04,0x88,0x02,0x11,0x11]*/constdata=Buffer.from([0x00,0x02,0x66,0x66,0x00,0x04,0x88,0x02,0x11,0x11]);/*构造两个缓冲区*data2_1包含:第一个数据包的全部数据,第二个数据包的部分数据*data2_2包含:第二个数据包的剩余数据*/constdata2_1=Buffer.from([0x00、0x00、0x00、0x02、0x66、0x66、0x00、0x04、0x88、0x02、0x11]);constdata2_2=Buffer.from([0x11]);//设置触发器stick.onData(function(data){console.log('receivedata,length:'+data.length);console.log(data)});stick.putData(数据);stick.putD阿塔(数据2_1);stick.putData(data2_2);//运行结果://接收数据,长度:4//接收数据,长度:6//接收数据,长度:2receivedata,length:4receivedata,length:6tcpclient和tcpserver之间的案例演示消息]了解详情。本demo主要演示TCP中处理粘包的方法。它不需要自己组装包头,直接发送和接收文本信息。组包解包操作就是这个类。该库已经封装在底层//Client.jsconstnet=require('net')conststick=require('../../index')constmsgCenter=newstick.msgCenter()constclient=net.createConnection({port:8080,host:'127.0.0.1'},function(){constmsgBuffer=msgCenter.publish('username=123&password=1234567,qwe')client.write(msgBuffer)})client.on('data',function(data){console.log(data.toString())})client.on('end',function(){console.log('disconnectfromserver')})//Server.jsconstnet=require('net')conststick=require('../../index')consttcp_server=net.createServer(function(socket){constmsgCenter=newstick.msgCenter()socket.on('data',function(data){msgCenter.putData(data)})msg??Center.onMsgRecv(function(data){console.log('recvdata:'+data.toString())})socket.on('close',function(error){console.log('clientdisconnected')})socket.on('error',function(error){console.log(`error:clientdisconnectedabnormally:${error}`)})})tcp_server.on('error',function(err){throwerr})tcp_server.listen(8080,function(){console.log('tcp_serverlisteningon8080')})[tcp-buffer]这个demo主要演示了TCP中字节流粘包的直接处理,展示了如何组装包头和包体并自行解包。如果不想自己拼包头解包,请看demotcp-msg//Clinet.jsconstnet=require('net')constclient=net.createConnection({port:8080,host:'127.0.0.1'},函数(){constbody=Buffer.from('username=123&password=1234567,qwe')//写入包头constheadBuf=newBuffer(4)headBuf.writeUInt32BE(body.byteLength,0)console.log('数据长度:'+headBuf.readInt32BE())//发送包头client.write(headBuf)//发送包内容client.write(body)console.log('databody:'+body.toString())})client.on('data',function(data){console.log(data.toString())})client.on('end',function(){console.log('disconnectfromserver')})//服务器.jsconstnet=require('net')conststick_package=require('../../index').stickconsttcp_server=net.createServer(function(socket){socket.stick=newstick_package(1024).setReadIntBE('32')socket.on('data',function(data){socket.stick.putData(data)})socket.stick.onData(function(data){//解析包头长度consthead=newBuffer(4)data.copy(head,0,0,4)//解析数据包内容constbody=newBuffer(head.readInt32BE())data.copy(body,0,4,head.readInt32BE())console.log('datalength:'+head.readInt32BE())console.log('bodycontent:'+body.toString())})socket.on('close',function(error){console.log('clientdisconnected')})socket.on('error',function(error){console.log(`error:Clientdisconnectedabnormally:${error}`)})})tcp_server.on('error',function(err){throwerr})tcp_server.listen(8080,function(){console.log('tcp_serverlisteningon8080')})LicenseMITCopyright(c)2017-present,ximen(G.doe)##[源码地址,喜欢请点star,订阅请收看】(https://github.com/lvgithub/stick)