Netty 应用:Socket服务器

Socket服务器

Netty作为Socket服务器,需要编写服务端和客户端,服务器端和客户端收发消息通过自定义的Handler.channelRead0方法来交互,客户端连接上服务器后,需要在active时向服务器发送一条消息来触发服务器的行为。

服务端实现

1/** 2 * Created by fubin on 2019/7/11. 3 */ 4public class SocketServer { 5 public static void main(String[] args) { 6 EventLoopGroup bossGroup = new NioEventLoopGroup(); 7 EventLoopGroup workerGroup = new NioEventLoopGroup(); 8 try{ 9 ServerBootstrap serverBootstrap = new ServerBootstrap(); 10 serverBootstrap.group(bossGroup,workerGroup) 11 .channel(NioServerSocketChannel.class) 12 .childHandler(new SocketServerInitializer()); 13 14 ChannelFuture channelFuture = serverBootstrap.bind(8899).sync(); 15 channelFuture.channel().closeFuture().sync(); 16 } catch (InterruptedException e) { 17 e.printStackTrace(); 18 } finally { 19 bossGroup.shutdownGracefully(); 20 workerGroup.shutdownGracefully(); 21 } 22 } 23} 24class SocketServerInitializer extends ChannelInitializer<SocketChannel>{ 25 protected void initChannel(SocketChannel socketChannel) throws Exception { 26 ChannelPipeline channelPipeline = socketChannel.pipeline(); 27 channelPipeline.addLast(new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE,0,4,0,4)); 28 channelPipeline.addLast(new LengthFieldPrepender(4)); 29 channelPipeline.addLast(new StringDecoder(CharsetUtil.UTF_8)); 30 channelPipeline.addLast(new StringEncoder(CharsetUtil.UTF_8)); 31 channelPipeline.addLast(new SocketServerHandler()); 32 } 33} 34class SocketServerHandler extends SimpleChannelInboundHandler<String>{ 35 protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception { 36 //远程地址 37 System.out.println(ctx.channel().remoteAddress()+","+msg); 38 //处理完业务,把结果返回给客户端 39 ctx.channel().writeAndFlush("from server:"+ UUID.randomUUID()); 40 } 41 @Override 42 public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { 43 super.exceptionCaught(ctx, cause); 44 //出现异常,关闭连接 45 ctx.close(); 46 } 47}

客户端实现

1/** 2 * Created by fubin on 2019/7/11. 3 */ 4public class SocketClient { 5 public static void main(String[] args) { 6 EventLoopGroup eventLoopGroup = new NioEventLoopGroup(); 7 8 try{ 9 Bootstrap bootstrap = new Bootstrap(); 10 bootstrap.group(eventLoopGroup).channel(NioSocketChannel.class).handler(new SocketClientInitializer()); 11 12 ChannelFuture future = bootstrap.connect("localhost",8899).sync(); 13 future.channel().closeFuture().sync(); 14 } catch (InterruptedException e) { 15 e.printStackTrace(); 16 } finally { 17 eventLoopGroup.shutdownGracefully(); 18 } 19 } 20} 21class SocketClientInitializer extends ChannelInitializer<SocketChannel>{ 22 protected void initChannel(SocketChannel ch) throws Exception { 23 ChannelPipeline channelPipeline = ch.pipeline(); 24 25 channelPipeline.addLast(new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE,0,4,0,4)); 26 channelPipeline.addLast(new LengthFieldPrepender(4)); 27 channelPipeline.addLast(new StringDecoder(CharsetUtil.UTF_8)); 28 channelPipeline.addLast(new StringEncoder(CharsetUtil.UTF_8)); 29 channelPipeline.addLast(new SocketClientHandler()); 30 } 31} 32class SocketClientHandler extends SimpleChannelInboundHandler<String>{ 33 protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception { 34 System.out.println(ctx.channel().remoteAddress()); 35 System.out.println("client output:"+msg); 36 ctx.channel().writeAndFlush("from client:"+ LocalDateTime.now()); 37 } 38 @Override 39 public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { 40 super.exceptionCaught(ctx, cause); 41 ctx.close(); 42 } 43 //在连接激活时,客户端向服务器发送一条消息 44 @Override 45 public void channelActive(ChannelHandlerContext ctx) throws Exception { 46 ctx.channel().writeAndFlush("hello world socket"); 47 } 48}

Socket实现的聊天程序消息群发

netty实现多客户端消息群发的关键 : ChannelGroup

服务端实现

1/** 2 * Created by fubin on 2019/7/11. 3 * 聊天程序,消息群发 4 */ 5public class ChatServer { 6 public static void main(String[] args) { 7 EventLoopGroup bossGroup = new NioEventLoopGroup(); 8 EventLoopGroup workerGroup = new NioEventLoopGroup(); 9 try{ 10 ServerBootstrap serverBootstrap = new ServerBootstrap(); 11 serverBootstrap.group(bossGroup,workerGroup) 12 .channel(NioServerSocketChannel.class) 13 .childHandler(new ChatServerInitializer()); 14 15 ChannelFuture channelFuture = serverBootstrap.bind(8899).sync(); 16 channelFuture.channel().closeFuture().sync(); 17 } catch (InterruptedException e) { 18 e.printStackTrace(); 19 } finally { 20 bossGroup.shutdownGracefully(); 21 workerGroup.shutdownGracefully(); 22 } 23 } 24} 25class ChatServerInitializer extends ChannelInitializer<SocketChannel> { 26 protected void initChannel(SocketChannel socketChannel) throws Exception { 27 ChannelPipeline channelPipeline = socketChannel.pipeline(); 28 //分隔符编解码器 29 channelPipeline.addLast(new DelimiterBasedFrameDecoder(4096, Delimiters.lineDelimiter())); 30 channelPipeline.addLast(new StringDecoder(CharsetUtil.UTF_8)); 31 channelPipeline.addLast(new StringEncoder(CharsetUtil.UTF_8)); 32 channelPipeline.addLast(new ChatServerHandler()); 33 } 34} 35class ChatServerHandler extends SimpleChannelInboundHandler<String> { 36 37 //保存channel对象 38 private static ChannelGroup channels = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE); 39 40 protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception { 41 Channel channel = ctx.channel(); 42 //广播消息 43 channels.forEach(ch ->{ 44 if(channel != ch){ 45 ch.writeAndFlush(channel.remoteAddress() + "发送的消息:"+ msg + "\n"); 46 }else{ 47 ch.writeAndFlush(" 【自己】" + msg + "\n"); 48 } 49 }); 50 } 51 @Override 52 public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { 53 super.exceptionCaught(ctx, cause); 54 //出现异常,关闭连接 55 ctx.close(); 56 } 57 /** 58 * 连接建立,告诉其他客户端,xxx已经上线 59 * @param ctx 60 * @throws Exception 61 */ 62 @Override 63 public void handlerAdded(ChannelHandlerContext ctx) throws Exception { 64 Channel channel = ctx.channel(); 65 //广播 66 channels.writeAndFlush("【服务器】 - " + channel.remoteAddress() + "加入\n"); 67 68 channels.add(channel); 69 } 70 @Override 71 public void handlerRemoved(ChannelHandlerContext ctx) throws Exception { 72 Channel channel = ctx.channel(); 73 //广播 74 channels.writeAndFlush("【服务器】 - " + channel.remoteAddress() + "离开\n"); 75 //此代码可不要,netty自动移除 76 //channels.remove(channel); 77 //验证 78 System.out.println("channelGroup size :"+channels.size()); 79 } 80 @Override 81 public void channelInactive(ChannelHandlerContext ctx) throws Exception { 82 Channel channel = ctx.channel(); 83 System.out.println("【服务器】- "+ channel.remoteAddress() + "下线\n"); 84 } 85 @Override 86 public void channelActive(ChannelHandlerContext ctx) throws Exception { 87 Channel channel = ctx.channel(); 88 System.out.println("【服务器】- "+ channel.remoteAddress() + "上线\n"); 89 } 90}

客户端实现

1/** 2 * Created by fubin on 2019/7/11. 3 */ 4public class ChatClient { 5 public static void main(String[] args) { 6 EventLoopGroup eventLoopGroup = new NioEventLoopGroup(); 7 8 try{ 9 Bootstrap bootstrap = new Bootstrap(); 10 bootstrap.group(eventLoopGroup).channel(NioSocketChannel.class).handler(new ChatClientInitializer()); 11 Channel channel = bootstrap.connect("localhost",8899).sync().channel(); 12 BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 13 //循环监听客户端输入 14 for(;;){ 15 channel.writeAndFlush(br.readLine()+"\r\n"); 16 } 17 } catch (InterruptedException | IOException e) { 18 e.printStackTrace(); 19 } finally { 20 eventLoopGroup.shutdownGracefully(); 21 } 22 } 23} 24class ChatClientInitializer extends ChannelInitializer<SocketChannel>{ 25 protected void initChannel(SocketChannel ch) throws Exception { 26 ChannelPipeline channelPipeline = ch.pipeline(); 27 28 channelPipeline.addLast(new DelimiterBasedFrameDecoder(4096, Delimiters.lineDelimiter())); 29 channelPipeline.addLast(new StringDecoder(CharsetUtil.UTF_8)); 30 channelPipeline.addLast(new StringEncoder(CharsetUtil.UTF_8)); 31 channelPipeline.addLast(new ChatClientHandler()); 32 } 33} 34class ChatClientHandler extends SimpleChannelInboundHandler<String>{ 35 protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception { 36 System.out.println(msg); 37 } 38}

应用内的推送的思考: 服务器端和客户端维持长连接推送给app,如果客户端断线,服务端需要把消息保存在数据库或者mongodb中,当客户端重连后,服务端再再重新发送。

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

2020年前端实用代码段,为你的工作保驾护航

有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )