TCP粘包拆包实例解析

tcp

TCP(transport control protocol,传输控制协议)是面向连接的,面向流的,提供高可靠性服务。收发两端(客户端和服务器端)都要有一一成对的socket,因此,发送端为了将多个发往接收端的包,更有效的发到对方,使用了优化方法(Nagle算法),将多次间隔较小且数据量小的数据,合并成一个大的数据块,然后进行封包。这样,接收端,就难于分辨出来了,必须提供科学的拆包机制。 即面向流的通信是无消息保护边界的

udp

UDP(user datagram protocol,用户数据报协议)是无连接的,面向消息的,提供高效率服务。不会使用块的合并优化算法,, 由于UDP支持的是一对多的模式,所以接收端的skbuff(套接字缓冲区)采用了链式结构来记录每一个到达的UDP包,在每个UDP包中就有了消息头(消息来源地址,端口等信息),这样,对于接收端来说,就容易进行区分处理了。 即面向消息的通信是有消息保护边界的。

粘包

1、发送端需要等缓冲区满才发送出去,有可能会发生两个数据接口的数据合并到一个缓冲区进行传输,造成粘包
2、接收方可能由于网络原因不及时接收缓冲区的包,造成多个包接收,形成粘包

拆包

当发送端缓冲区的长度大于网络的数据链路层的最大传送单元时,tcp会将数据拆成几个数据包发送出去,形成拆包

字节序概念

比如,一个占据四个字节的 16 进制数0x12345678,决定其大小的最重要的字节是“12”,最不重要的是“78”。小端字节序将最不重要的字节排在前面,储存顺序就是78563412;大端字节序则完全相反,将最重要的字节排在前面,储存顺序就是12345678。

as代码实例

			this.socket = new Socket();
			this.socket.endian = Endian.BIG_ENDIAN;//大端字节序
			this.socket.timeout = _timeout;
			this.socket.connect(serverIp, serverPort);
			this.socket.addEventListener(Event.CONNECT, onSocketConnected);
			this.socket.addEventListener(Event.CLOSE, onSocketClosed);
			this.socket.addEventListener(IOErrorEvent.IO_ERROR, onSocketError);
			this.socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onSecErrorHandler);
			this.socket.addEventListener(ProgressEvent.SOCKET_DATA, onSocketRecvData);
			private function onSocketRecvData(event:ProgressEvent):void{
			while (true){
				if (dataLen == 0){//数据包长度判断
					if (!socket.connected){
						return;
					}if (socket.bytesAvailable < 5){//这边5是看发送端和接收端之间定义的协议,当前这边前四个字节指定包的长度,第五个字节表示包是否压缩
						break;
					}
					dataLen = socket.readInt()-1;//包长度
					recvCompressFlag = socket.readByte();//是否压缩
				}else{
					if (socket.bytesAvailable < dataLen){//如果可读数据长度小于包长,没必要读取数据,等待下次数据包到来再进行读取(这边就是拆包的处理方式)
						break;
					}
					var bytes:ByteArray = new ByteArray();
					bytes.objectEncoding = ObjectEncoding.AMF3;//编码格式
					bytes.endian = Endian.BIG_ENDIAN;//数据的字节读取顺序
					socket.readBytes(bytes, 0, dataLen);//读取字节流数据,只读取对应包的数据长度,这边可能会发生粘包情况,剩余的包数据循环再次读取
					dataLen = 0;//重置数据包长度
					if(recvCompressFlag){
					   bytes.uncompress();
					}
					onPacket(bytes);//解析数据包
				}
			}
		}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值