省级门户网站建设,设计网站界面,织梦做的网站怎么样,建设网站长沙1. TCP数据传输粘包简介
在本系列的第6篇文章《鸿蒙网络编程系列6-TCP数据粘包表现及原因分析》中#xff0c;我们演示了TCP数据粘包的表现#xff0c;如图所示#xff1a; 随后解释了粘包背后的可能原因#xff0c;并给出了解决TCP传输粘包问题的两种思路#xff0c;第一…1. TCP数据传输粘包简介
在本系列的第6篇文章《鸿蒙网络编程系列6-TCP数据粘包表现及原因分析》中我们演示了TCP数据粘包的表现如图所示 随后解释了粘包背后的可能原因并给出了解决TCP传输粘包问题的两种思路第一种是指定数据包结束标志在本系列第35篇《鸿蒙网络编程系列35-通过数据包结束标志解决TCP粘包问题》中给出了具体的实现第二种是通过固定包头指定包的长度本文将通过一个示例演示这种思路的实现。
2. 固定包头可变包体解决TCP粘包问题演示
本示例运行后的界面如图所示 和上一篇文章类似输入服务端的地址这里可以使用本系列第25篇文章《鸿蒙网络编程系列25-TCP回声服务器的实现》中创建的TCP回声服务器也可以使用其他类似的回声服务器然后输入服务器端口最后单击测试按钮循环发送0到99的数字字符串到服务端服务端会回传收到的信息本示例在收到服务器信息后在日志区域输出如图所示 从中可以看出这次也彻底解决了数据粘包问题收到的信息和发送时保持一致。
3. 固定包头可变包体解决TCP粘包问题示例编写
下面详细介绍创建该示例的步骤。 步骤1创建Empty Ability项目。
步骤2在module.json5配置文件加上对权限的声明
requestPermissions: [{name: ohos.permission.INTERNET}]这里添加了访问互联网的权限。
步骤3在Index.ets文件里添加如下的代码
import { socket } from kit.NetworkKit;
import { Decimal, util, buffer } from kit.ArkTS;
import { BusinessError } from kit.BasicServicesKit;Entry
Component
struct Index {State title: string 固定包头可变包体演示示例;//服务端端口号State port: number 9990//服务端IP地址State serverIp: string //操作日志State msgHistory: string //最大缓存长度maxBufSize: number 1024 * 8//接收数据缓冲区receivedDataBuf: buffer.Buffer buffer.alloc(this.maxBufSize)//缓冲区已使用长度receivedDataLen: number 0//日志显示区域的滚动容器scroller: Scroller new Scroller()build() {Row() {Column() {Text(this.title).fontSize(14).fontWeight(FontWeight.Bold).width(100%).textAlign(TextAlign.Center).padding(10)Flex({ justifyContent: FlexAlign.Start, alignItems: ItemAlign.Center }) {Text(服务端地址:).fontSize(14).width(90)TextInput({ text: this.serverIp }).onChange((value) {this.serverIp value}).height(40).width(80).fontSize(14).flexGrow(1)Text(:).fontSize(14)TextInput({ text: this.port.toString() }).onChange((value) {this.port parseInt(value)}).height(40).width(70).fontSize(14)Button(测试).onClick(() {this.test()}).height(40).width(60).fontSize(14)}.width(100%).padding(10)Scroll(this.scroller) {Text(this.msgHistory).textAlign(TextAlign.Start).padding(10).width(100%).backgroundColor(0xeeeeee)}.align(Alignment.Top).backgroundColor(0xeeeeee).height(300).flexGrow(1).scrollable(ScrollDirection.Vertical).scrollBar(BarState.On).scrollBarWidth(20)}.width(100%).justifyContent(FlexAlign.Start).height(100%)}.height(100%)}//测试async test() {//服务端地址let serverAddress: socket.NetAddress { address: this.serverIp, port: this.port, family: 1 }//执行TCP通讯的对象let tcpSocket: socket.TCPSocket socket.constructTCPSocketInstance()//收到消息时的处理tcpSocket.on(message, (value: socket.SocketMessageInfo) {this.receiveMsgFromServer(value)})await tcpSocket.connect({ address: serverAddress }).then(() {this.msgHistory 连接成功\r\n;}).catch((e: BusinessError) {this.msgHistory 连接失败 ${e.message} \r\n;})//循环发送0到99的数字字符串到服务端for (let i 0; i 100; i) {let msg i.toString()await this.sendMsg2Server(tcpSocket, msg)let sleepTime Decimal.random().toNumber() 0.5//休眠sleepTime时间大概0.5毫秒到1.5毫秒await sleep(sleepTime)}}//发送数据到服务端async sendMsg2Server(tcpSocket: socket.TCPSocket, msg: string) {let textEncoder new util.TextEncoder();let encodeValue textEncoder.encodeInto(msg)let sendBuf buffer.alloc(2 encodeValue.byteLength)//写入固定包头中的长度信息sendBuf.writeUInt16LE(encodeValue.byteLength)//写入可变包体信息sendBuf.write(msg, 2)await tcpSocket.send({ data: sendBuf.buffer })}//读取服务端发送过来的数据receiveMsgFromServer(value: socket.SocketMessageInfo) {//把接收到的数据复制到缓冲区有效数据尾部let copyCount buffer.from(value.message).copy(this.receivedDataBuf, this.receivedDataLen)this.receivedDataLen copyCount//至少写入了3个字节才需要解析if (this.receivedDataLen 3) {return;}//当前数据包长度let packLen this.receivedDataBuf.readUInt16LE()let textDecoder util.TextDecoder.create(utf-8);//当前数据包长度加上固定包体的2字节如果小于等于缓冲区已使用长度就可以解析while ((packLen 2) this.receivedDataLen) {//把可变包体中的数据转换为字符串let msgArray new Uint8Array(this.receivedDataBuf.subarray(2, packLen 2).buffer);let msg textDecoder.decodeToString(msgArray)//剩余的未解析数据let leaveBufData this.receivedDataBuf.subarray(packLen 2, this.receivedDataLen)//剩余的未解析数据移动到缓冲区头部for (let pos 0; pos leaveBufData.length; pos) {this.receivedDataBuf.writeUInt8(leaveBufData.readUInt8(pos), pos)}//重新设置缓冲区已使用长度this.receivedDataLen leaveBufData.length//输出接收的数据到日志this.msgHistory S: msg \r\n//至少写入了3个字节才需要解析否则跳出循环if (this.receivedDataLen 3) {break;}//开始查找下一个固定包头中的可变包体长度packLen this.receivedDataBuf.readUInt16LE()}this.scroller.scrollEdge(Edge.Bottom)}
}//休眠指定的毫秒数
function sleep(time: number): Promisevoid {return new Promise((resolve) setTimeout(resolve, time));
}步骤4编译运行可以使用模拟器或者真机。
步骤5按照本文第2部分“数据包结束标志解决TCP粘包问题演示”操作即可。
4. 代码分析
本示例的关键点在于构造数据包的格式具体数据包的格式是这样的前两个字节为固定的包长度使用小端的16位无符号整数表示后面是包内容。以发送数据包为例代码如下所示 async sendMsg2Server(tcpSocket: socket.TCPSocket, msg: string) {let textEncoder new util.TextEncoder();let encodeValue textEncoder.encodeInto(msg)let sendBuf buffer.alloc(2 encodeValue.byteLength)//写入固定包头中的长度信息sendBuf.writeUInt16LE(encodeValue.byteLength)//写入可变包体信息sendBuf.write(msg, 2)await tcpSocket.send({ data: sendBuf.buffer })}这里首先把要发送的内容编码为Uint8Array类型然后为缓冲区分配长度长度为内容编码后的长度加上2随后把内容长度作为无符号数写入缓冲区然后把发送的内容也写入缓冲区最后使用TCP客户端发送缓冲区到服务端。
接收时首先把所有收到的数据都复制到接收缓冲区中然后从缓冲区头部取两个字节作为数据包内容长度然后判断接收缓冲区中已接收的数据是不是大于等于数据包内容长度加2如果是说明接收到了完整的数据包就可以从中提取内容了提取完毕把剩下的缓冲区数据移动到缓冲区头部继续下一次循环从缓冲区中提取完整数据包的数据知道已接收的缓冲区小于数据包长度加2为止。相关代码位于方法receiveMsgFromServer中源码包含了详细的注释这里就不再赘述了。
本文作者原创除非明确授权禁止转载
本文源码地址 https://gitee.com/zl3624/harmonyos_network_samples/tree/master/code/tcp/PacketHeadWithLen
本系列源码地址 https://gitee.com/zl3624/harmonyos_network_samples 文章转载自: http://www.morning.spxsm.cn.gov.cn.spxsm.cn http://www.morning.lnrr.cn.gov.cn.lnrr.cn http://www.morning.pinngee.com.gov.cn.pinngee.com http://www.morning.bnmfq.cn.gov.cn.bnmfq.cn http://www.morning.kqhlm.cn.gov.cn.kqhlm.cn http://www.morning.hmbtb.cn.gov.cn.hmbtb.cn http://www.morning.kmqjx.cn.gov.cn.kmqjx.cn http://www.morning.prqdr.cn.gov.cn.prqdr.cn http://www.morning.mbfkt.cn.gov.cn.mbfkt.cn http://www.morning.jpzcq.cn.gov.cn.jpzcq.cn http://www.morning.wnkbf.cn.gov.cn.wnkbf.cn http://www.morning.guofenmai.cn.gov.cn.guofenmai.cn http://www.morning.lblsx.cn.gov.cn.lblsx.cn http://www.morning.rynq.cn.gov.cn.rynq.cn http://www.morning.txysr.cn.gov.cn.txysr.cn http://www.morning.zgdnz.cn.gov.cn.zgdnz.cn http://www.morning.ylmxs.cn.gov.cn.ylmxs.cn http://www.morning.ssrjt.cn.gov.cn.ssrjt.cn http://www.morning.lzqtn.cn.gov.cn.lzqtn.cn http://www.morning.rhkgz.cn.gov.cn.rhkgz.cn http://www.morning.tkryt.cn.gov.cn.tkryt.cn http://www.morning.fcwb.cn.gov.cn.fcwb.cn http://www.morning.xctdn.cn.gov.cn.xctdn.cn http://www.morning.mqghs.cn.gov.cn.mqghs.cn http://www.morning.ckcjq.cn.gov.cn.ckcjq.cn http://www.morning.bpncd.cn.gov.cn.bpncd.cn http://www.morning.pnfwd.cn.gov.cn.pnfwd.cn http://www.morning.mhmcr.cn.gov.cn.mhmcr.cn http://www.morning.lwbhw.cn.gov.cn.lwbhw.cn http://www.morning.lwrks.cn.gov.cn.lwrks.cn http://www.morning.addai.cn.gov.cn.addai.cn http://www.morning.pqcsx.cn.gov.cn.pqcsx.cn http://www.morning.qnkqk.cn.gov.cn.qnkqk.cn http://www.morning.qbgff.cn.gov.cn.qbgff.cn http://www.morning.plflq.cn.gov.cn.plflq.cn http://www.morning.tslfz.cn.gov.cn.tslfz.cn http://www.morning.lsyk.cn.gov.cn.lsyk.cn http://www.morning.rqjxc.cn.gov.cn.rqjxc.cn http://www.morning.rshs.cn.gov.cn.rshs.cn http://www.morning.pmbcr.cn.gov.cn.pmbcr.cn http://www.morning.mkyxp.cn.gov.cn.mkyxp.cn http://www.morning.czrcf.cn.gov.cn.czrcf.cn http://www.morning.mrskk.cn.gov.cn.mrskk.cn http://www.morning.qjsxf.cn.gov.cn.qjsxf.cn http://www.morning.tnhqr.cn.gov.cn.tnhqr.cn http://www.morning.rongxiaoman.com.gov.cn.rongxiaoman.com http://www.morning.ydrml.cn.gov.cn.ydrml.cn http://www.morning.nbgfk.cn.gov.cn.nbgfk.cn http://www.morning.lnrhk.cn.gov.cn.lnrhk.cn http://www.morning.ntyks.cn.gov.cn.ntyks.cn http://www.morning.lhwlp.cn.gov.cn.lhwlp.cn http://www.morning.hffpy.cn.gov.cn.hffpy.cn http://www.morning.qbwyd.cn.gov.cn.qbwyd.cn http://www.morning.fkmqg.cn.gov.cn.fkmqg.cn http://www.morning.gmyhq.cn.gov.cn.gmyhq.cn http://www.morning.mhnr.cn.gov.cn.mhnr.cn http://www.morning.dplmq.cn.gov.cn.dplmq.cn http://www.morning.wrlcy.cn.gov.cn.wrlcy.cn http://www.morning.zfyr.cn.gov.cn.zfyr.cn http://www.morning.qfkxj.cn.gov.cn.qfkxj.cn http://www.morning.qnkqk.cn.gov.cn.qnkqk.cn http://www.morning.bfnbn.cn.gov.cn.bfnbn.cn http://www.morning.wqngt.cn.gov.cn.wqngt.cn http://www.morning.yqyhr.cn.gov.cn.yqyhr.cn http://www.morning.lnwdh.cn.gov.cn.lnwdh.cn http://www.morning.bwrbm.cn.gov.cn.bwrbm.cn http://www.morning.ftrpvh.cn.gov.cn.ftrpvh.cn http://www.morning.qgkcs.cn.gov.cn.qgkcs.cn http://www.morning.ltpph.cn.gov.cn.ltpph.cn http://www.morning.pnmgr.cn.gov.cn.pnmgr.cn http://www.morning.bfbl.cn.gov.cn.bfbl.cn http://www.morning.gbsfs.com.gov.cn.gbsfs.com http://www.morning.jbqwb.cn.gov.cn.jbqwb.cn http://www.morning.ghrhb.cn.gov.cn.ghrhb.cn http://www.morning.qdxwf.cn.gov.cn.qdxwf.cn http://www.morning.qnhpq.cn.gov.cn.qnhpq.cn http://www.morning.bsxws.cn.gov.cn.bsxws.cn http://www.morning.fgqbx.cn.gov.cn.fgqbx.cn http://www.morning.tlpgp.cn.gov.cn.tlpgp.cn http://www.morning.lbjdx.cn.gov.cn.lbjdx.cn