当前位置: 首页 > wzjs >正文

怎么做外卖网站.net响应式网站模板

怎么做外卖网站,.net响应式网站模板,google cloud 永久免费,装修平台app什么是粘包和拆包?在网络编程中,粘包和拆包是两个常见的问题:粘包(TCP粘包):多个小数据包被合并成一个大数据包发送拆包(TCP拆包):一个大数据包被分割成多个小数据包发送…

什么是粘包和拆包?

在网络编程中,粘包和拆包是两个常见的问题:

  • 粘包(TCP粘包):多个小数据包被合并成一个大数据包发送
  • 拆包(TCP拆包):一个大数据包被分割成多个小数据包发送

为什么会出现粘包和拆包?

1. TCP协议特性

TCP是面向流的协议,数据以字节流的形式传输,没有明确的消息边界。TCP会根据网络状况自动调整发送策略:

// 示例:发送方连续发送多个消息
socket.getOutputStream().write("Hello".getBytes());
socket.getOutputStream().write("World".getBytes());
socket.getOutputStream().write("Netty".getBytes());

接收方可能收到:

  • "HelloWorldNetty" (粘包)
  • "Hello" + "WorldNetty" (部分粘包)
  • "He" + "lloWorld" + "Netty" (拆包)
2. 缓冲区机制

TCP有发送缓冲区和接收缓冲区,数据在缓冲区中可能被合并或分割:

// 发送缓冲区示例
ByteBuffer sendBuffer = ByteBuffer.allocate(1024);
sendBuffer.put("Hello".getBytes());
sendBuffer.put("World".getBytes());
// 缓冲区满了才发送,导致粘包
3. Nagle算法

TCP的Nagle算法会将多个小包合并成一个大包发送,减少网络开销

Netty解决方案

1. 固定长度方案
public class FixedLengthFrameDecoder extends ByteToMessageDecoder {private final int frameLength;public FixedLengthFrameDecoder(int frameLength) {this.frameLength = frameLength;}@Overrideprotected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {// 检查是否有足够的数据while (in.readableBytes() >= frameLength) {// 读取固定长度的数据ByteBuf frame = in.readBytes(frameLength);out.add(frame);}}
}// 使用示例
pipeline.addLast(new FixedLengthFrameDecoder(10));

优点:实现简单,性能好

缺点:不够灵活,可能造成数据浪费

2. 分隔符方案
public class DelimiterBasedFrameDecoder extends ByteToMessageDecoder {private final ByteBuf delimiter;public DelimiterBasedFrameDecoder(ByteBuf delimiter) {this.delimiter = delimiter;}@Overrideprotected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {// 查找分隔符位置int delimiterIndex = indexOf(in, delimiter);if (delimiterIndex >= 0) {// 读取到分隔符的数据ByteBuf frame = in.readBytes(delimiterIndex);// 跳过分隔符in.skipBytes(delimiter.capacity());out.add(frame);}}private int indexOf(ByteBuf haystack, ByteBuf needle) {// 实现查找分隔符的逻辑for (int i = haystack.readerIndex(); i < haystack.writerIndex() - needle.capacity() + 1; i++) {boolean found = true;for (int j = 0; j < needle.capacity(); j++) {if (haystack.getByte(i + j) != needle.getByte(j)) {found = false;break;}}if (found) {return i - haystack.readerIndex();}}return -1;}
}// 使用示例
ByteBuf delimiter = Unpooled.copiedBuffer("\n".getBytes());
pipeline.addLast(new DelimiterBasedFrameDecoder(delimiter));
3. 长度字段方案(推荐)
public class LengthFieldBasedFrameDecoder extends ByteToMessageDecoder {private final int maxFrameLength;private final int lengthFieldOffset;private final int lengthFieldLength;private final int lengthAdjustment;private final int initialBytesToStrip;public LengthFieldBasedFrameDecoder(int maxFrameLength,int lengthFieldOffset,int lengthFieldLength,int lengthAdjustment,int initialBytesToStrip) {this.maxFrameLength = maxFrameLength;this.lengthFieldOffset = lengthFieldOffset;this.lengthFieldLength = lengthFieldLength;this.lengthAdjustment = lengthAdjustment;this.initialBytesToStrip = initialBytesToStrip;}@Overrideprotected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {// 检查是否有足够的数据读取长度字段if (in.readableBytes() < lengthFieldOffset + lengthFieldLength) {return;}// 标记当前读取位置int actualLengthFieldOffset = in.readerIndex() + lengthFieldOffset;// 读取长度字段long frameLength = getUnadjustedFrameLength(in, actualLengthFieldOffset, lengthFieldLength);// 计算实际帧长度frameLength += lengthAdjustment + lengthFieldOffset + lengthFieldLength;// 检查帧长度是否合理if (frameLength < 0) {in.skipBytes(lengthFieldLength);throw new CorruptedFrameException("negative pre-adjustment length field: " + frameLength);}if (frameLength > maxFrameLength) {in.skipBytes(lengthFieldLength);throw new TooLongFrameException("Adjusted frame length (" + frameLength + ") is greater than maxFrameLength (" + maxFrameLength + ")");}// 检查是否有完整的帧if (in.readableBytes() < frameLength) {return;}// 跳过指定的字节数in.skipBytes(initialBytesToStrip);// 读取帧数据int readerIndex = in.readerIndex();int actualFrameLength = (int) frameLength - initialBytesToStrip;ByteBuf frame = in.retainedSlice(readerIndex, actualFrameLength);in.skipBytes(actualFrameLength);out.add(frame);}protected long getUnadjustedFrameLength(ByteBuf buf, int offset, int length) {long frameLength;switch (length) {case 1:frameLength = buf.getUnsignedByte(offset);break;case 2:frameLength = buf.getUnsignedShort(offset);break;case 3:frameLength = buf.getUnsignedMedium(offset);break;case 4:frameLength = buf.getUnsignedInt(offset);break;case 8:frameLength = buf.getLong(offset);break;default:throw new DecoderException("unsupported lengthFieldLength: " + length + " (expected: 1, 2, 3, 4, or 8)");}return frameLength;}
}

Netty内置的解决方案

1. FixedLengthFrameDecoder
// 固定长度解码器
public class FixedLengthServer {public static void main(String[] args) throws Exception {EventLoopGroup bossGroup = new NioEventLoopGroup(1);EventLoopGroup workerGroup = new NioEventLoopGroup();try {ServerBootstrap bootstrap = new ServerBootstrap();bootstrap.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class).childHandler(new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel ch) throws Exception {ChannelPipeline pipeline = ch.pipeline();// 固定长度解码器,每个消息10字节pipeline.addLast(new FixedLengthFrameDecoder(10));pipeline.addLast(new StringDecoder());pipeline.addLast(new FixedLengthHandler());}});ChannelFuture future = bootstrap.bind(8080).sync();System.out.println("固定长度服务器启动成功");future.channel().closeFuture().sync();} finally {bossGroup.shutdownGracefully();workerGroup.shutdownGracefully();}}
}class FixedLengthHandler extends ChannelInboundHandlerAdapter {@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {String message = (String) msg;System.out.println("收到消息: [" + message + "]");ctx.writeAndFlush("收到: " + message + "\n");}
}
2. DelimiterBasedFrameDecoder
// 分隔符解码器
public class DelimiterServer {public static void main(String[] args) throws Exception {EventLoopGroup bossGroup = new NioEventLoopGroup(1);EventLoopGroup workerGroup = new NioEventLoopGroup();try {ServerBootstrap bootstrap = new ServerBootstrap();bootstrap.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class).childHandler(new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel ch) throws Exception {ChannelPipeline pipeline = ch.pipeline();// 使用换行符作为分隔符ByteBuf delimiter = Unpooled.copiedBuffer("\n".getBytes());pipeline.addLast(new DelimiterBasedFrameDecoder(1024, delimiter));pipeline.addLast(new StringDecoder());pipeline.addLast(new DelimiterHandler());}});ChannelFuture future = bootstrap.bind(8081).sync();System.out.println("分隔符服务器启动成功");future.channel().closeFuture().sync();} finally {bossGroup.shutdownGracefully();workerGroup.shutdownGracefully();}}
}class DelimiterHandler extends ChannelInboundHandlerAdapter {@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {String message = (String) msg;System.out.println("收到消息: [" + message + "]");ctx.writeAndFlush("收到: " + message + "\n");}
}
3. LengthFieldBasedFrameDecoder(最常用)
// 长度字段解码器
public class LengthFieldServer {public static void main(String[] args) throws Exception {EventLoopGroup bossGroup = new NioEventLoopGroup(1);EventLoopGroup workerGroup = new NioEventLoopGroup();try {ServerBootstrap bootstrap = new ServerBootstrap();bootstrap.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class).childHandler(new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel ch) throws Exception {ChannelPipeline pipeline = ch.pipeline();// 长度字段解码器配置// maxFrameLength: 最大帧长度// lengthFieldOffset: 长度字段偏移量// lengthFieldLength: 长度字段长度// lengthAdjustment: 长度调整值// initialBytesToStrip: 跳过的字节数pipeline.addLast(new LengthFieldBasedFrameDecoder(65535, 0, 4, 0, 4));pipeline.addLast(new StringDecoder());pipeline.addLast(new LengthFieldHandler());}});ChannelFuture future = bootstrap.bind(8082).sync();System.out.println("长度字段服务器启动成功");future.channel().closeFuture().sync();} finally {bossGroup.shutdownGracefully();workerGroup.shutdownGracefully();}}
}class LengthFieldHandler extends ChannelInboundHandlerAdapter {@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {String message = (String) msg;System.out.println("收到消息: [" + message + "]");ctx.writeAndFlush("收到: " + message + "\n");}
}

最后

Netty提供了多种TCP粘包、拆包问题的解决方案:

  1. FixedLengthFrameDecoder:适合固定长度消息
  2. DelimiterBasedFrameDecoder:适合文本协议
  3. LengthFieldBasedFrameDecoder:最灵活,适合二进制协议
  4. 自定义编解码器:完全控制协议格式

在实际项目中,建议优先使用Netty内置的解码器,只有在特殊需求时才考虑自定义实现。

http://www.dtcms.com/wzjs/597337.html

相关文章:

  • 品牌网站建设预算wordpress搬迁后台总跳转到老网站
  • 在网站后台挂马网站搜索框怎么做
  • 电子商务网站的优点有那些双辽做网站
  • 主题资源网站制作平台免费发布推广信息网站
  • 网站备案查询工信部appwordpress 403错误
  • 华艺网站开发学校二级网站建设自查情况
  • 萍乡网站推广谷歌seo搜索优化
  • 相机拍照的图片怎么做网站呀网页微信版下载
  • 不锈钢公司网站源码 网站建设 产品3级分类asp源码网站菜单导航制作
  • 网站收录提交入口大全网站的建站标准
  • 手机网站设计字体大小新手小白怎么做跨境电商
  • 完整域名展示网站源码怀化市住房与城乡建设厅网站
  • 北京网站设计工作室做网站开发的薪酬怎么样
  • 文化投资的微网站怎么做seo网站外包公司
  • 家乡网站建设策划案高级网络规划师报考条件
  • 吉林市网站建设招标wordpress 游客投稿
  • 什么是网站建设从哪些方面建设网站青岛网站制作工作室
  • 微信网站开发 新闻小米市场营销案例分析
  • 网站做自动群发百度搜录头像 wordpress
  • 江北网站建设如何用word做简单的网站
  • 那些网站主做玄幻小说地推app推广赚佣金
  • 国外创意海报设计网站做装修行业营销型网站
  • 济南网站建设哪里有做证
  • 旅游响应式网站建设新网站怎么做排名
  • 螺蛳粉的软文推广长沙企业关键词优化
  • 做公益网站的原因wordpress使用教程
  • dw网页设计软件的学习网站怎么找网站做公示
  • 无锡网络建站旅游主题网站怎么做
  • 让别人做一个网站需要多少钱网络优化需要哪些知识
  • 成品网站 子目录打不开网上做翻译兼职网站