最近有做毕业设计,需要大量用到网络相关的东西,之前也用socket 写过一些东西,但是感觉直接用socket太费事了。所以就利用现成的框架工具,来做了。找一些东西,最后选择用netty。 netty 是一个异步网络编程框架。他在发送数据和接收数据都是异步的。他提供了许多扩展,利用他可以省好多事。
利用socket或者基于流的传输协议会出现一些问题。netty的官方教程中也提到了。原文是这样的:
引用
In a stream-based transport such as TCP/IP, received data is stored into a socket receive buffer. Unfortunately, the buffer of a stream-based transport is not a queue of packets but a queue of bytes. It means, even if you sent two messages as two independent packets, an operating system will not treat them as two messages but as just a bunch of bytes. Therefore, there is no guarantee that what you read is exactly what your remote peer wrote. For example, let us assume that the TCP/IP stack of an operating system has received three packets:
+-----+-----+-----+
| ABC | DEF | GHI |
+-----+-----+-----+
Because of this general property of a stream-based protocol, there's high chance of reading them in the following fragmented form in your application:
+----+-------+---+---+
| AB | CDEFG | H | I |
+----+-------+---+---+
Therefore, a receiving part, regardless it is server-side or client-side, should defrag the received data into one or more meaningful frames that could be easily understood by the application logic. In case of the example above, the received data should be framed like the following:
+-----+-----+-----+
| ABC | DEF | GHI |
+-----+-----+-----+
小弟不才,原文大概的意思是这样的:
引用
在例如 TCP/IP 这样基于流的传输过程中,接收到的数据是存储在socket接收缓冲区中。不幸的是,基于流的缓冲区里的顺序不是按照包的顺序,而是按照字节的顺序。也就是说,即使你通过两个独立的包发送了两个消息,但操作系统不会把他们当做两个独立的消息,而是字节串。因此,你读取到的是与远端写的一致性是无法保证的。例如,让我们假设有这样的操作系统已经接收到的TCP/IP数据包的栈:
+-----+-----+-----+
| ABC | DEF | GHI |
+-----+-----+-----+
因为基于流协议的通常特性,很可能应用程序以下面的顺序读取数据:
+----+-------+---+---+
| AB | CDEFG | H | I |
+----+-------+---+---+
因此,在接收数据的时候,无论是服务端还是客户端,都应该将接收到的数据组织成有意义的帧(frame),从而更简单的处理应用逻辑。之前的例子,接收到的数据应该被封成这样的帧:
+-----+-----+-----+
| ABC | DEF | GHI |
+-----+-----+-----+
我在开发过程中也确实遇到这样的问题,netty的官方教程也在接下来讲了解决方法。但可能为让读者更深刻的理解netty,用的是比较底层的api。其实netty应对 拆包与组包,已经有解决方法。netty 有一个包 org.jboss.netty.handler.codec.frame ,这个包里面有三种解决方法,都是对 netty 的 codec 进行的扩展。其中 1.DelimiterBasedFrameDecoder 是利用分隔符来进行包的界定;2.FixedLengthFrameDecoder 是利用固定的长度来进行包的界定;3.LengthFieldBasedFrameDecoder 和 LengthFieldPrepender 是利用在发送数据的时候在里面加上头字段,头字段里面包含了包的长度。
这三种方面我用到了其中两种(DelimiterBasedFrameDecoder 和 LengthFieldBasedFrameDecoder)。
举一个 LengthFieldBasedFrameDecoder 的例子
服务器端
ServerBootstrap serverBootstrap = new ServerBootstrap(new NioServerSocketChannelFactory(Executors.newCachedThreadPool(), Executors.newCachedThreadPool()));
serverBootstrap.setPipelineFactory(new ChannelPipelineFactory() {
@Override
public ChannelPipeline getPipeline() throws Exception {
ChannelPipeline pipeline = org.jboss.netty.channel.Channels.pipeline();
pipeline.addLast(Constants.LOGGING_HANDLER, new LoggingHandler());
pipeline.addLast(Constants.UP_FRAME_HANDLER, new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 0, 2, 0, 2));
pipeline.addLast(Constants.DOWN_FRAME_HANDLER, new LengthFieldPrepender(2, false));
//add customer handler
pipeline.addLast("myHandler", new ServerMessageHandler());
return pipeline;
}
});
serverBootstrap.bind(new InetSocketAddress(9999));
客户端
ClientBootstrap clientBootstrap = new ClientBootstrap(new NioClientSocketChannelFactory(Executors.newCachedThreadPool(), Executors.newCachedThreadPool()));
clientBootstrap.setPipelineFactory(new ChannelPipelineFactory() {
@Override
public ChannelPipeline getPipeline() throws Exception {
ChannelPipeline pipeline = org.jboss.netty.channel.Channels.pipeline();
pipeline.addLast(Constants.LOGGING_HANDLER, new LoggingHandler());
pipeline.addLast(Constants.UP_FRAME_HANDLER, new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 0, 2, 0, 2));
pipeline.addLast(Constants.DOWN_FRAME_HANDLER, new LengthFieldPrepender(2, false));
//add customer handler
clientMessageHandler = new ClientMessageHandler();
pipeline.addLast("myHandler", clientMessageHandler);
return pipeline;
}
});
clientBootstrap.connect(new InetSocketAddress(9999));
分享到:
相关推荐
Netty粘包分包现象及解决方案实战,防socket攻击水。
netty的知识,主要是解决拆包粘包的问题、内部含有客户端断线重连的代码,非常适合netty入门
Netty粘包拆包解决方案.docx
这是一个java web项目集成了netty websocket的...初始化握手对象时指定了maxFramePayloadLength 的长度、以及通过配置netty内置解码器处理数据半包等方法,均无效。以下是终极解决办法,供大家参考和解决这样的问题。
主要介绍了使用Netty解决TCP粘包和拆包问题过程详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
注:下载前请查看本人博客文章,看是否...里面包含模拟TCP客户端发送报文工具,硬件厂商提供的协议,服务端(springboot+netty)解析报文源码,源码里整合了redis,不需要可自行删除,如有需要客户端代码,可联系我。
Netty (netty-netty-4.0.56.Final.tar.gz)是一个 NIO 客户端服务器框架,可以快速轻松地开发协议服务器和客户端等...因此,Netty 成功地找到了一种方法,可以在不妥协的情况下实现易于开发、性能、稳定性和灵活性。
Netty基础,用于学习Netty,参考黑马程序员的netty教程
springboot整合 netty做心跳检测 springboot整合 netty做心跳检测 springboot整合 netty做心跳检测 springboot整合 netty做心跳检测 springboot整合 netty做心跳检测 springboot整合 netty做心跳检测 springboot整合...
Netty (netty-netty-3.10.6.Final.tar.gz)是一个 NIO 客户端服务器框架,可以快速轻松地开发协议服务器和客户端等...因此,Netty 成功地找到了一种方法,可以在不妥协的情况下实现易于开发、性能、稳定性和灵活性。
Netty (netty-netty-5.0.0.Alpha2.tar.gz)是一个 NIO 客户端服务器框架,可以快速轻松地开发协议服务器和客户端等...因此,Netty 成功地找到了一种方法,可以在不妥协的情况下实现易于开发、性能、稳定性和灵活性。
Netty断线重连解决方案.docx
《Netty进阶之路:跟着案例学Netty》中的案例涵盖了Netty...在案例的分析过程中,还穿插讲解了Netty的问题定位思路、方法、技巧,以及解决问题使用的相关工具,对读者在实际工作中用好Netty具有很大的帮助和启发作用。
netty-3.2.5.Final.jar netty包
netty-buffer-4.1.32.Final-sources.jar netty-buffer-4.1.32.Final.jar netty-build-22-sources.jar netty-build-22.jar netty-codec-4.1.32.Final-sources.jar netty-codec-4.1.32.Final.jar netty-codec-...
在案例的分析过程中,还穿插讲解了Netty的问题定位思路、方法、技巧,以及解决问题使用的相关工具,对读者在实际工作中用好Netty具有很大的帮助和启发作用。本书适合架构师、设计师、开发工程师、测试工程师,以及对...
Netty入门教程
跟闪电侠学Netty:Netty即时聊天实战与底层原理-book-netty
使用Netty搭建WebSocket服务器,该资源示范如何修改单包大小限制,解决不能发送大数据包的问题。
一种基于NETTY的远程过程调用方法.pdf