精通并发与netty(socket编程详解)

netty在socket编程中的作用:

  1. socket开发,可以开发客户端和服务端,微服务开发底层也是用netty来进行数据传输
  2. Netty可以支持长连接开发,http连接可以称之为短连接,服务端向客户端推送消息就需要使用websocket。如果是用netty可以只传送所需的数据,还可以自定义协议开发。定义请求头,请求体,请求格式,请求结尾什么

如下案例将展示netty服务端与多个客户端进行socket通讯

服务端代码:

public class MyChatServer {
	
	public static void main(String[] args) throws Exception {
		
		EventLoopGroup bossGroup = new NioEventLoopGroup();
		EventLoopGroup workerGroup  = new NioEventLoopGroup();
		
		try{
			ServerBootstrap bootstrap = new ServerBootstrap();
			bootstrap.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class)
			.childHandler(new MyChatServerInitializer());
			
			ChannelFuture future = bootstrap.bind(8899).sync();
			future.channel().closeFuture().sync();
			
		}finally{
			bossGroup.shutdownGracefully();
			workerGroup.shutdownGracefully();
		}
	}
}

MyChatServerInitializer.java

public class MyChatServerInitializer extends  ChannelInitializer<SocketChannel>{
	@Override
	protected void initChannel(SocketChannel ch) throws Exception {
		ChannelPipeline pipeline = ch.pipeline();
		//DelimiterBasedFrameDecoder :netty定制的解码器,主要根据分隔符进行解析
		pipeline.addLast(new DelimiterBasedFrameDecoder(4096,Delimiters.lineDelimiter()));
		pipeline.addLast(new StringDecoder(CharsetUtil.UTF_8));
		pipeline.addLast(new StringEncoder(CharsetUtil.UTF_8));
		pipeline.addLast(new MyChatServerHandler());//对于一对多的链接方式的处理
	}
}

MyChatServerHandler.java

/**
 * 消息广播的实现
 * 服务器启动 然后会有多个用户与服务器进行建立连接 且服务端会打印出***已经上线
 * 并且会在其他客户端打印出***上线
 * 如果客户端断开与服务器的链接,则会在控制台中输出***下线,同时广播其他客户端***已经下线
 */
public class MyChatServerHandler extends SimpleChannelInboundHandler<String> {

	//channelGroup:保存所有与服务器端链接的客户端的channel对象
	private static ChannelGroup channelGroup  = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);

	protected void channelRead0(ChannelHandlerContext ctx, String msg)
			throws Exception {
		Channel channel = ctx.channel(); //发送消息的channel对象
		//把自己挑出来
		channelGroup.forEach(ch->{
			if(channel != ch){ //不是自己
				ch.writeAndFlush(channel.remoteAddress() +"发送的消息: "+msg+"\n");
			}else{
				//是自己
				ch.writeAndFlush("【自己】"+msg + "\n");
			}
		});
	}
	@Override//链接建立
	public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
		Channel channel = ctx.channel(); //链接对象
		//广播  服务端保存所有链接对象 
		//channelGroup 中的writeAndFlush方法会将内容写入到所有的channel中
		channelGroup.writeAndFlush("[服务器-]"+channel.remoteAddress()+ "加入\n");
		channelGroup.add(channel);
	}
	
	@Override //链接断了
	public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
		Channel channel = ctx.channel();
		//如果该链接断了,那么netty会自动将这个channel移除出channelGroup
		channelGroup.writeAndFlush("[服务器]-"+channel.remoteAddress()+"离开\n");
		System.out.println(channelGroup.size());
	}
	
	@Override //活动状态
	public void channelActive(ChannelHandlerContext ctx) throws Exception {
		Channel channel = ctx.channel();
		System.out.println(channel.remoteAddress() +"-已经上线了");
	}
	
	@Override
	public void channelInactive(ChannelHandlerContext ctx) throws Exception {
		Channel channel = ctx.channel();
		System.out.println(channel.remoteAddress()+"-已经下线了");
	}
	
	@Override
	public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)
			throws Exception {
		cause.printStackTrace();
		ctx.close();
	}
}

 

客户端的实现:

MyChatClientServer.java

public class MyChatClientServer {
	
	public static void main(String[] args) throws Exception {
		
		EventLoopGroup eventGroup = new NioEventLoopGroup();
		try{
			Bootstrap bootstrap = new Bootstrap();
			bootstrap.group(eventGroup).channel(NioSocketChannel.class)
			.handler(new MyChatClientInitializer());
			Channel channel = bootstrap.connect("localhost",8899).sync().channel();
			//读取控制台输入的内容
			BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
			//死循环,等待键盘输入
			for(;;){
				channel.writeAndFlush(br.readLine()+"\r\n");
			}
		}finally{
			eventGroup.shutdownGracefully(); 
		}
	}
}

MyChatClientInitializer.java

public class MyChatClientInitializer extends ChannelInitializer<SocketChannel> {
	
	protected void initChannel(SocketChannel ch) throws Exception {
		
		ChannelPipeline pipeline = ch.pipeline();
		pipeline.addLast(new DelimiterBasedFrameDecoder(4096,Delimiters.lineDelimiter()));
		pipeline.addLast(new StringDecoder(CharsetUtil.UTF_8));
		pipeline.addLast(new StringEncoder(CharsetUtil.UTF_8));
		pipeline.addLast(new MyChatClientHandler());
	};
}

MyChatClientHandler.java

public class MyChatClientHandler extends SimpleChannelInboundHandler<String> {
	@Override
	protected void channelRead0(ChannelHandlerContext ctx, String msg)
			throws Exception {
		System.out.println(msg);
	}
}

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
精通并发netty视频教程(2018)视频教程 netty视频教程 Java视频教程目录: 1_学习的要义 2_Netty宏观理解 3_Netty课程大纲深度解读 4_项目环境搭建与Gradle配置 5_Netty执行流程分析与重要组件介绍 6_Netty回调与Channel执行流程分析 7_NettySocket编程详解 8_Netty多客户端连接与通信 9_Netty读写检测机制与长连接要素 10_Netty对WebSocket的支援 11_Netty实现服务器端与客户端的长连接通信 12_Google Protobuf详解 13_定义Protobuf文件及消息详解 14_Protobuf完整实例详解 15_Protobuf集成Netty与多协议消息传递 16_Protobuf多协议消息支援与工程最佳实践 17_Protobuf使用最佳实践与Apache Thrift介绍 18_Apache Thrift应用详解与实例剖析 19_Apache Thrift原理与架构解析 20_通过Apache Thrift实现Java与Python的RPC调用 21_gRPC深入详解 22_gRPC实践 23_Gradle Wrapper在Gradle项目构建中的最佳实践 24_gRPC整合Gradle与代码生成 25_gRPC通信示例与JVM回调钩子 26_gRPC服务器流式调用实现 27_gRPC双向流式数据通信详解 28_gRPC与Gradle流畅整合及问题解决的完整过程与思考 29_Gradle插件问题解决方案与Nodejs环境搭建 30_通过gRPC实现Java与Nodejs异构平台的RPC调用 31_gRPC在Nodejs领域中的静态代码生成及与Java之间的RPC通信 32_IO体系架构系统回顾与装饰模式的具体应用 33_Java NIO深入详解与体系分析 34_Buffer中各重要状态属性的含义与关系图解 35_Java NIO核心类源码解读与分析 36_文件通道用法详解 37_Buffer深入详解 38_NIO堆外内存与零拷贝深入讲解 39_NIO中Scattering与Gathering深度解析 40_Selector源码深入分析 41_NIO网络访问模式分析 42_NIO网络编程实例剖析 43_NIO网络编程深度解析 44_NIO网络客户端编写详解 45_深入探索Java字符集编解码 46_字符集编解码全方位解析 47_Netty服务器与客户端编码模式回顾及源码分析准备 48_Netty与NIO系统总结及NIO与Netty之间的关联关系分析 49_零拷贝深入剖析及用户空间与内核空间切换方式 50_零拷贝实例深度剖析 51_NIO零拷贝彻底分析与Gather操作在零拷贝中的作用详解 52_NioEventLoopGroup源码分析与线程数设定 53_Netty对Executor的实现机制源码分析 54_Netty服务端初始化过程与反射在其中的应用分析 55_Netty提供的Future与ChannelFuture优势分析与源码讲解 56_Netty服务器地址绑定底层源码分析 57_Reactor模式透彻理解及其在Netty中的应用 58_Reactor模式与Netty之间的关系详解 59_Acceptor与Dispatcher角色分析 60_Netty的自适应缓冲区分配策略与堆外内存创建方式 61_Reactor模式5大角色彻底分析 62_Reactor模式组件调用关系全景分析 63_Reactor模式与Netty组件对比及Acceptor组件的作用分析 64_Channel与ChannelPipeline关联关系及模式运用 65_ChannelPipeline创建时机与高级拦截过滤器模式的运用 66_Netty常量池实现及ChannelOption与Attribute作用分析 67_Channel与ChannelHandler及ChannelHandlerContext之间的关系分析 68_Netty核心四大组件关系与构建方式深度解读 69_Netty初始化流程总结及Channel与ChannelHandlerContext作用域分析 70_Channel注册流程深度解读 71_Channel选择器工厂与轮询算法及注册底层实现 72_Netty线程模型深度解读与架构设计原则 73_Netty底层架构系统总结与应用实践 74_Netty对于异步读写操作的架构思想与观察者模式的重要应用 75_适配器模式与模板方法模式在入站处理器中的应用 76_Netty项目开发过程中常见且重要事项分析 77_Java NIO Buffer总结回顾与难点拓展 78_Netty数据容器ByteBuf底层数据结构深度剖析 79_Netty
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值