网络编程复习(十):实践----数据通信

来源:互联网 发布:java管理系统有哪些 编辑:程序博客网 时间:2024/06/01 14:18

这里说一下真实项目应用中使用Netty的场景,大体上一些参数的设置都是根据服务器的性能决定的,这不是我要说的事。

我们要考虑得是2台机器(或者多台)使用Netty进行的通信,大体上分为三种:

第一种:使用长连接的通道不断开的方式进行通信,也就是客户端和服务端的通道一直处于开启状态,如果服务器性能足够好,并且我们的客户端数量也比较少的情况下,这种方式可以考虑使用。

第二种:一次性批量提交数据,采用短连接方式,也就是我们会把数据保存在本地临时缓冲区或者临时表当中,当达到临界值的时候进行一次性批量提交,又或者根据定时任务轮询提交,这种情况弊端是做不到实时性传输,在对实施性不高的应用中建议使用。

第三种:我们可以使用一种特殊的长连接方式,在指定的某一段时间内,服务端与客户端没有任何通信,则断开连接,下次连接则是客户端向服务端发起请求的时候,再次建立连接,但是这种情况我们必须考虑2个因素:

一:如何在超时(即服务端与客户端没有任何通信)后关闭通道?关闭通道后又如何再次建立连接;

二:客户端宕机时,我们无需考虑,下次客户端重启之后即可再次与服务端建立连接,但如果是服务器宕机,我们的客户端如何与服务端建立连接呢?


因为前面所有的基本都是第一种方式,这里就不再赘述,第二种不好模拟,这里做一下第三种:

在这里我开启了一个子线程模拟客户端断开后进行重连操作:这里的request和response以及对应的handler类和MyMarshallingFactory类都和上一章一样,这里不再重复粘贴,看下代码:

client:

package cn.lh.netty2;import java.util.concurrent.TimeUnit;import io.netty.bootstrap.Bootstrap;import io.netty.channel.ChannelFuture;import io.netty.channel.ChannelInitializer;import io.netty.channel.EventLoopGroup;import io.netty.channel.nio.NioEventLoopGroup;import io.netty.channel.socket.SocketChannel;import io.netty.channel.socket.nio.NioSocketChannel;import io.netty.handler.timeout.ReadTimeoutHandler;public class NettyClient {private static class SingalInstance{static final NettyClient instance = new NettyClient();}public static NettyClient getInstance(){return SingalInstance.instance;}private EventLoopGroup group;private Bootstrap bootstrap;private ChannelFuture cf;private NettyClient(){group = new NioEventLoopGroup();bootstrap = new Bootstrap();bootstrap.group(group) .channel(NioSocketChannel.class) .handler(new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel ch) throws Exception {ch.pipeline().addLast(MyMarshallingFactory.buildMarshallingDecoder());ch.pipeline().addLast(MyMarshallingFactory.buildMarshallingEncoder());ch.pipeline().addLast(new ReadTimeoutHandler(5));ch.pipeline().addLast(new NettyClientHandler());}});}public void connect(){try {this.cf = bootstrap.connect("127.0.0.1", 8888).sync();System.out.println("远程服务器已经连接,可以开始通信");} catch (Exception e) {e.printStackTrace();}}public ChannelFuture getFuture(){if(this.cf == null){this.connect();}if(!this.cf.channel().isActive()){this.connect();}return this.cf;}public static void main(String[] args) throws InterruptedException {final NettyClient client = NettyClient.getInstance();ChannelFuture future = client.getFuture();for(int i=0;i<=3;i++){Request request = new Request();request.setId(i);request.setMsg("请求消息"+i);future.channel().writeAndFlush(request);TimeUnit.SECONDS.sleep(4);}future.channel().closeFuture().sync();new Thread(new Runnable() {public void run() {try {System.out.println("进入了子线程");ChannelFuture f = client.getFuture();System.out.println(f.channel().isOpen());System.out.println(f.channel().isActive());Request request = new Request();request.setId(50);request.setMsg("子线程请求消息");f.channel().writeAndFlush(request);f.channel().closeFuture().sync();System.out.println("子线程模拟结束");} catch (Exception e) {// TODO: handle exception}}}).start();System.out.println("连接结束,关闭客户端");}}

server类:

package cn.lh.netty2;import io.netty.bootstrap.ServerBootstrap;import io.netty.channel.ChannelFuture;import io.netty.channel.ChannelInitializer;import io.netty.channel.ChannelOption;import io.netty.channel.EventLoopGroup;import io.netty.channel.nio.NioEventLoopGroup;import io.netty.channel.socket.SocketChannel;import io.netty.channel.socket.nio.NioServerSocketChannel;import io.netty.handler.timeout.ReadTimeoutHandler;public class NettyServer {public static void main(String[] args) throws InterruptedException {EventLoopGroup boss = new NioEventLoopGroup();EventLoopGroup worker = new NioEventLoopGroup();ServerBootstrap bootstrap = new ServerBootstrap();bootstrap.group(boss, worker) .option(ChannelOption.SO_BACKLOG, 1024) .option(ChannelOption.SO_KEEPALIVE, true) .option(ChannelOption.SO_SNDBUF, 32*1024) .option(ChannelOption.SO_RCVBUF, 32*1024) .channel(NioServerSocketChannel.class) .childHandler(new ChannelInitializer<SocketChannel>() {@Overridepublic void initChannel(SocketChannel ch) throws Exception {ch.pipeline().addLast(MyMarshallingFactory.buildMarshallingDecoder());ch.pipeline().addLast(MyMarshallingFactory.buildMarshallingEncoder());ch.pipeline().addLast(new ReadTimeoutHandler(5));ch.pipeline().addLast(new NettyServerHandler());}});ChannelFuture f = bootstrap.bind(8888).sync();f.channel().closeFuture().sync();boss.shutdownGracefully();worker.shutdownGracefully(); }}

看下结果:

client:

远程服务器已经连接,可以开始通信server response:0--回应消息0server response:1--回应消息1server response:2--回应消息2server response:3--回应消息3连接结束,关闭客户端进入了子线程远程服务器已经连接,可以开始通信truetrueserver response:50--回应消息50子线程模拟结束
server:

client request:0请求消息0client request:1请求消息1client request:2请求消息2client request:3请求消息3io.netty.handler.timeout.ReadTimeoutExceptionclient request:50子线程请求消息io.netty.handler.timeout.ReadTimeoutException

关于其中的逻辑其实很简单,大家注意ChannelFuture的获取方式,我认为没有什么值得好说的,有一些java基础的应该都可以看懂。

原创粉丝点击