TCP粘包和拆包

粘包拆包


TCP是面向连接的,面向流的,提供了可靠的连接。

发送端为了提高效率,采用了Nagle算法,将多次间隔小数据量小的包,合并成一个大的数据块,然后进行分

包。

这样做虽然提高了效率,但是接收端无法分辨出完整的数据包。因为面向流的通信是无消息保护边界的。

TCP无消息保护边界,需要在接收端处理消息边界问题,也就是粘包拆包。

粘包:发送两个数据包,前一个数据包和后一个数据包粘在一起
拆包:发送一个数据包,接收端分两段接收。

解决方案


发送数据时,把此次发送的数据的长度也发送过去。根据长度了接收数据,就不会出现多读或者少读的问题。

示例:

存放数据的类

public class Message {
	// byte数组的长度
    private int len;

    private byte[] content;

    // getter setter 
}

解码器

public class MessageDecoder extends ReplayingDecoder<Void> {

    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
        System.out.println("Decoder被调用");
        int len = in.readInt();
        byte[] content = new byte[len];
        // 此处不需要判断readableBytes >= len,ReplayingDecoder会自动根据长度判断
        in.readBytes(content);
        Message message = new Message(len, content);
        out.add(message);
    }
}

编码器

public class MessageEncoder extends MessageToByteEncoder<Message> {
    @Override
    protected void encode(ChannelHandlerContext ctx, Message msg, ByteBuf out) throws Exception {
        System.out.println("MessageEncoder被调用");
        int len = msg.getLen();
        byte[] content = msg.getContent();
        out.writeInt(len);
        out.writeBytes(content);
    }
}

添加编码器和解码器

pipeline.addLast(new MessageDecoder());
pipeline.addLast(new MessageEncoder());

发送

// 发送
byte[] content = str.getBytes(CharsetUtil.UTF_8);
int len = content.length;
Message message = new Message(len, content);
ctx.writeAndFlush(message);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值