TCP-IP学习笔记七:Netty使用--简单通信编程3
来源:互联网 发布:各编程语言比较 编辑:程序博客网 时间:2024/05/31 18:39
TCP/IP学习笔记七:Netty使用–简单通信编程3
标签(空格分隔): Netty 网络编程
TCP-IP学习笔记五:Netty使用–简单通信编程1
TCP-IP学习笔记六:Netty使用–简单通信编程2
对于上个程序,对对象类型的传输,发送单个数据没有任何问题,运行很正常,当我们一次发送多个请求(包含多个对象)还是这样正常?会出现什么问题?
对客户端【IO事件处理类】代码进行修改:
/** * 发送请求 */ @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { for (int i = 0; i < 5; i++) { ctx.writeAndFlush(new User(i, "guozh"+i)); } }
运行结果:
服务器端: 服务器监听8989端口 解码···· 客户端发请求了···服务器接收的数据:User [id=0, name=guozh0] 编码····客户端: 编码···· 编码···· 编码···· 编码···· 编码···· 解码···· 客户端接收的响应:User [id=0, name=guozh0]
为什么会出现客户端发送多次请求,而服务器端只收了一次请求和返回一次响应呢?了解TCP/IP协议的可能知道为什么,因为出现了TCP粘包/拆包现象。
TCP粘包/拆包
TCP是一个“流”协议,就是没有界限的一串数据。大家可以想想河里的流水,他们汇成一片,没有分界线。TCP底层并不了解上层业务数据的具体含义,它会根据TCP缓冲区的实际情况进行包的划分,所以在业务上认为,一个完成的包可能会被TCP拆分成多个包进行发送,也可能把多个小包封装成一个大数据包发送,这就是TCP粘包和拆包问题。
参考:Netty权威指南第四章
如图所示:
如何解决粘包/拆包问题?
服务器端【注册IO事件类】代码:
package com.netty.demo3.server;import com.netty.demo2.ObjectCodec;import io.netty.channel.ChannelInitializer;import io.netty.channel.socket.SocketChannel;import io.netty.handler.codec.LengthFieldBasedFrameDecoder;import io.netty.handler.codec.LengthFieldPrepender;public class ServerChannelInitializer extends ChannelInitializer<SocketChannel> { /** * 注册IO事件处理类 */ @Override protected void initChannel(SocketChannel ch) throws Exception { //添加的长度 ch.pipeline().addLast(new LengthFieldPrepender(2)); /* * maxFrameLength 最大的长度 * lengthFieldOffset 从那开始 * lengthFieldLength 读入长度 * lengthAdjustment * initialBytesToStrip 截取几个字节 */ ch.pipeline().addLast(new LengthFieldBasedFrameDecoder(65535, 0, 2, 0, 2)); ch.pipeline().addLast(new ObjectCodec()); ch.pipeline().addLast(new ServerRequestResponseHander()); }}
客户端【注册IO事件类】代码:
package com.netty.demo3.client;import com.netty.demo2.ObjectCodec;import io.netty.channel.ChannelInitializer;import io.netty.channel.socket.SocketChannel;import io.netty.handler.codec.LengthFieldBasedFrameDecoder;import io.netty.handler.codec.LengthFieldPrepender;public class ClientChannelInitializer extends ChannelInitializer<SocketChannel> { /** * 注册IO事件处理类 */ @Override protected void initChannel(SocketChannel ch) throws Exception { ch.pipeline().addLast(new LengthFieldPrepender(2)); ch.pipeline().addLast(new LengthFieldBasedFrameDecoder(65535, 0, 2, 0, 2)); ch.pipeline().addLast(new ObjectCodec()); ch.pipeline().addLast(new ClientRequestResponseHander()); }}
其他类不做修改。
Netty给我们提供了两个方法:LengthFieldBasedFrameDecoder和LengthFieldPrepender多粘包/拆包的支持。详细介绍参考:Netty权威指南第七章
执行结果:
服务器: 服务器监听8989端口 解码···· 客户端发请求了···服务器接收的数据:User [id=0, name=guozh0] 编码···· 解码···· 客户端发请求了···服务器接收的数据:User [id=1, name=guozh1] 编码···· 解码···· 客户端发请求了···服务器接收的数据:User [id=2, name=guozh2] 编码···· 解码···· 客户端发请求了···服务器接收的数据:User [id=3, name=guozh3] 编码···· 解码···· 客户端发请求了···服务器接收的数据:User [id=4, name=guozh4] 编码····客户端: 编码···· 编码···· 编码···· 编码···· 编码···· 解码···· 客户端接收的响应:User [id=0, name=guozh0] 解码···· 客户端接收的响应:User [id=1, name=guozh1] 解码···· 客户端接收的响应:User [id=2, name=guozh2] 解码···· 客户端接收的响应:User [id=3, name=guozh3] 解码···· 客户端接收的响应:User [id=4, name=guozh4]
总结:
主要是对于多线程问题出现数据问题的处理。粘包和拆包,多线程下数据的传输等问题。
0 0
- TCP-IP学习笔记七:Netty使用--简单通信编程3
- TCP-IP学习笔记五:Netty使用--简单通信编程1
- TCP-IP学习笔记六:Netty使用--简单通信编程2
- TCP/IP网络编程 学习笔记_12 --进程间通信
- Android端使用Netty框架实现TCP/IP通信
- TCP-IP学习笔记二:NIO的网络编程Buffer简单使用
- TCP/IP学习笔记(七)
- TCP/IP学习笔记(七)
- TCP/IP学习笔记(七)
- TCP/IP学习笔记(七)
- TCP/IP学习笔记(七)
- 【tcp-ip学习总结】使用tcp协议实现简单的通信小程序
- TCP/IP网络编程 学习笔记_4 --OSI七层网络模型
- TCP/IP学习笔记之七 --- IP选路
- 学习笔记七之网络编程(TCP)
- 学习笔记七之网络编程(TCP)
- Java Netty 学习笔记(二)使用Netty编程
- TCP/IP网络编程学习笔记
- <十四> 文件系统的移植
- 给定一个数组,其中只有一个数出现一次,别的数都出现3次,找出这个数
- SortedSet接口与TreeSet实现类(一)
- 钱多的花不完是种怎样的体验?看老外如何花样炫富!
- Android异步加载(慕课网学习笔记)
- TCP-IP学习笔记七:Netty使用--简单通信编程3
- JZOJ4816. label
- npm scripts 使用指南
- 字符串匹配的KMP算法
- Linux下安装Tomcat服务器和部署Web应用
- 22个HTML5初级技巧
- 多线程实现数据库的并发操作
- 插入排序/选择排序/交换排序/归并排序/基数排序
- Java的作业