netty实现一个简单的服务端和客户端通信

netty java Nio网络通信框架,能接收TCP,http,webSocket,UDP

elk包括:logStash,Elasticsearch,Kibana
LogStash:tcp监听netty服务器发送的信息,并把消息处理好后转发给ES
Elasticsearch:接受LogStash发送来的数据,并进行分词构建索引。
kibana:主要是从ES中获取相关索引的数据进行检索,分析。默认端口5601
顺序:pc网页 通过http--->Netty高性能服务器-->LogStash数据收集器(过滤处理)-->Elasticsearch搜索引擎(构建索引)-->kibana展示分析
手机app 通过tcp---->同上


netty 3个核心功能:
1.Extensible Event Model可以扩展的事件模型。
2.Universal communication api 普通的通信API。
3.zero-copy-Capable Rich Byte Buffer 零拷贝


案例1.1
netty服务端:ServerBootstrap.java是netty的启动辅助类
public class NettyServer{
public static void main(String[]args){
1.绑定两个线程组分别用来处理客户端通道的accept和读写事件
2.绑定服务端通道NioServerSocketChannel
3.给读写事件的线程通道 绑定handler 去真正处理读写
4.监听端口
ServerBootstrap server = new ServerBootstrap();//netty启动类
EventLoopGroup parentGroup = new NioEventLoopGroup();
EventLoopGroup childgroup = new NioEventLoopGroup();
server.group(parentGroup,childgroup);//parentGroup用来处理accept事件,childgroup用来处理通道的读写事件
server.channel(NioServerSocketChannel.class);//第2部绑定某个通道
server.childHandler(new ChannelInitializer<SocketChannel>(){//绑定handler,真正的处理,childHandler给子线程组绑定handler, ChannelInitializer是给通道初始化
@Override
protected void initChannel(SocketChannel ch) throws Exception{ //处理他的读写事件
// ch.pipeline().addLast(new DelimiterBasedFrameDecoder(   //解码器,一定要加在SimpleServerHandler 的上面
// Integer.MAX_VALUE,Delimiters.lineDelimiter()[0])) ;//maxFrameLength表示这一贞最大的大小 ,delimiter分隔符 0就是 \r \n的组合或者-->Unpooled.wrappedBuffer(new byte[]{'\r','\n'})
//解码器,接收的数据 进行解码
ch.pipeline().addLast(new LengthFieldBasedFrameDecoder(//长度解码器
Integer.MAX_VALUE,0,4,0,4)); //参数1这一贞最大长度,参数2 lengthFieldOffset长度偏移量,参数3 lengthFieldLength 传递的长度 获取前面4个字符,参数4 lengthAdjustment 长度需要调节 0为不需要调节 1为增加一个字节,参数5 initialBytesToStrip 需要跳过多少长度 跳过4个字节,int是4个字节

ch.pipeline().addLast(new SimpleServerHandler());
//下面是2个编码器,向socket传递的数据("is ok")进行编码,顺序是倒过来执行的。因为是个双向链表 ??
ch.pipeline().addLast(new LengthFieldPrepender(4,false)); //这个编码器只能编码byteBuf. 参数1 长度 4个字节, 参数2 lengthIncludesLengthFieldLength 长度是否包含了这个长度 false不包含   
ch.pipeline().addLast(new StringEncoder()); //把传过来的数据 转换成byteBuf
}
});
ChannelFuture future = server.bind(8080).sync();//第4步 绑定端口
future.channel().closeFuture().sync();//当通道关闭了,就继续往下走
}
}
public class SimpleServerHandler extends ChannelInboundHandlerAdapter{
//可以在这里面写一套类似springMVC的框架
//让SimpleServerHandler不跟任何业务有关,可以封装一套框架
@Override  //读取客户端通道的数据
public void channelRead(ChannelHandlerContext ctx,Object msg) throws Exception{
//super.channelRead(ctx,msg);
if(msg instanceof ByteBuf){
System.out.println(((ByteBuf)msg).toString(Charset.defaultCharset()));
}

//业务逻辑代码处理框架。。。

//告诉客户端,我已经读到你的数据了
ctx.channel().writeAndFlush("is ok");
}
}
//使用下面语句测试上面代码。1.开启上面main方法。2.执行一下命令
c:>telnet localhost 8080
随便输入,会发现eclipse控制台会监听到输入的内容,有个问题 接收时一个字一个字接受,可以让他一行一行接收


socket端,向上面的netty发送数据
public class SocketClient{

public static void main(String[]args){
Socket socket = new Socket("loclhost",8080);//netty和socket通信
DataOutputStream output = new DataOutputStream(socket.getOutputStream());//netty和socket通信
output.writeInt(4);//写入4 ,
output.writeBytes("ssssss\r\naaaaaaa");   //写数据给netty服务器
output.flush();
//socket接受netty传过来的数据
DataInputStream input = new DataInputStream(socket.getInputStream());
int length = input.readInt(); //获取传来的数据 的长度
byte[] b = new byte[length];
input.readFully(b,0,length);
System.out.println(new String(b));
socket.close();
}
}


案例1.2:netty客户端 向cs发送数据
使用Bootstrap.java启动netty
public class NettyClient{
public static vlid main(String[]args){
Bootstrap client = new Bootstrap();//netty的启动类
//绑定线程组,处理读写和链接事件
EventLoopGroup group = new NioEventLoopGroup();
cilent.group(group);//第1步.绑定线程组//netty只有一个线程组管理,因为构造没有accept实现?
//第2步 绑定客户端通道
client.channel(NioSocketChannel.class);
//第3步 给NIoSocketChannel初始化handler,真正的处理读写事件
client.handler(new ChannelInitializer<NioSocketChannel>(){ //通道是NioSocketChannel
@Override
protected void initChannel(NioSocketChannel ch){
ch.pipeline().addLast(new SimpleClientHandler()); //找到他的管道 增加他的handler

ch.pipelien().addLast(new LengthFieldPrepender(4,false));//是个长度编码器
ch.pipelien().addLast(new StringEchoder());//字符串编码器

}
});
//第4步 只要链接即可
ChannelFuture future = client.connect("loaclhost",8080).sync(); //同步返回sync()
//发送数据给服务器
String msg = "hello netty";//需要加字符串编码器
future.channel().writeAndFlush(msg);

future.channel().closeFuture.sync();
System.out.println("客户端运行完毕");
}
}
public class SimpleClientHandler extends ChannelInboundHandlerAdapter{
@Override
public void channelRead(ChannelHandlerContext ctx,Object msg) throws Exception{
//接收服务器端传过来的数据
if(msg instanceof ByteBuf){
System.out.println( ((ByteBuf)msg).toString(Charset.defaultCharset()));
}
ctx.channel().close(); //把客户端的通道关闭

}
}
测试:启动NettyServer.java,再启动NettyClient.java ,netty服务器会接收到信息


案例2 netty和spring整合:
@Configuration   //相当于把该类作为spring的xml配置文件中的<beans>
@ComponentScan("bauble2")
public class SpringServer{
public static void main(){
//使用ApplicationContext构建spring容器 //ApplicationContext借口没有start方法所以使用AnnotationConfigApplicationContext定义deriving definition
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringServer.class);
context.start();
//启动之后 想要主线程挂到这里,增加同步机制
synchronized (SpringServer.class){
try{
SpringServer.class.wait();
}catch(InterruptedException e){
e.printStackTrace();
}
}
}
}
www.itjoin.org/course/findLatest
//跟netty整合, 可以在这里面写一套类似springMVC的框架
@Component //注入到spring容器里面
public class InitNetty implements ApplicationListener<ContextRefreshedEvent>{ //ContextRefreshedEvent当整个容器刷新的时候触发
@Override
public void onApplicationEvent(ContextRefreshedEvent event){
new NettyThread().start();
}
}
//new 一个线程
public class NettyThread extends Thread{
@Override
public void run(){
//启动netty
dostart();
}
private void dostart(){
1.绑定两个线程组分别用来处理客户端通道的accept和读写事件
2.绑定服务端通道NioServerSocketChannel
3.给读写事件的线程通道 绑定handler 去真正处理读写
4.监听端口
try{
ServerBootstrap server = new ServerBootstrap();//netty启动类
EventLoopGroup parentGroup = new NioEventLoopGroup();
EventLoopGroup childgroup = new NioEventLoopGroup();
server.group(parentGroup,childgroup);//parentGroup用来处理accept事件,childgroup用来处理通道的读写事件
server.channel(NioServerSocketChannel.class);//第2部绑定某个通道
server.childHandler(new ChannelInitializer<SocketChannel>(){//绑定handler,真正的处理,childHandler给子线程组绑定handler, ChannelInitializer是给通道初始化
@Override
protected void initChannel(SocketChannel ch) throws Exception{ //处理他的读写事件
// ch.pipeline().addLast(new DelimiterBasedFrameDecoder(   //解码器,一定要加在SimpleServerHandler 的上面
// Integer.MAX_VALUE,Delimiters.lineDelimiter()[0])) ;//maxFrameLength表示这一贞最大的大小 ,delimiter分隔符 0就是 \r \n的组合或者-->Unpooled.wrappedBuffer(new byte[]{'\r','\n'})
//解码器,接收的数据 进行解码
ch.pipeline().addLast(new LengthFieldBasedFrameDecoder(//长度解码器
Integer.MAX_VALUE,0,4,0,4)); //参数1这一贞最大长度,参数2 lengthFieldOffset长度偏移量,参数3 lengthFieldLength 传递的长度 获取前面4个字符,参数4 lengthAdjustment 长度需要调节 0为不需要调节 1为增加一个字节,参数5 initialBytesToStrip 需要跳过多少长度 跳过4个字节,int是4个字节

ch.pipeline().addLast(new SimpleServerHandler());
//下面是2个编码器,向socket传递的数据("is ok")进行编码,顺序是倒过来执行的。因为是个双向链表 ??
ch.pipeline().addLast(new LengthFieldPrepender(4,false)); //这个编码器只能编码byteBuf. 参数1 长度 4个字节, 参数2 lengthIncludesLengthFieldLength 长度是否包含了这个长度 false不包含   
ch.pipeline().addLast(new StringEncoder()); //把传过来的数据 转换成byteBuf
}
});
ChannelFuture future = server.bind(8080).sync();//第4步 绑定端口
future.channel().closeFuture().sync();//当通道关闭了,就继续往下走
}catch(InterruptedException e){
e.printStackTrace();
}
}
}

测试:启动SpringServer.jave ,再 启动NettyClient.java,会有信息返回。 InitNetty 会在spring启动的时候启动,因为ContextRefreshedEvent监听 spring的启动

------

假如写一套ElasticSearch底层分布式RPC,    或者Dubbo分布式RPC

需要写netty RPC架构
netty客户端异步获取相应结果到主线程     《服务器架构实现   客户端与服务端架构通信》
netty做长链接的时候 需要注意哪些地方。
1。需要心跳检测机制,保证链接的稳定。 
2.考虑重连,容易丢包。
3.采用连接池,netty自带的连接池
netty底层实现原理,(netty线程模型---读写半包处理---内存池管理)
netty UerverBootstrap如何启动和处理channel的Accept事件
NioEventLoop接收channel read事件剖析。如何处理netty的读写事件
如何处理读写半包
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!
要用 Netty 编写一个 Socket 服务端实现和多个客户端通信,需要遵循以下步骤: 1. 创建 ServerBootstrap 实例并设置相关参数。 ```java EventLoopGroup bossGroup = new NioEventLoopGroup(); EventLoopGroup workerGroup = new NioEventLoopGroup(); try { ServerBootstrap b = new ServerBootstrap(); b.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) .option(ChannelOption.SO_BACKLOG, 100) .handler(new LoggingHandler(LogLevel.INFO)) .childHandler(new ChannelInitializer<SocketChannel>() { @Override public void initChannel(SocketChannel ch) throws Exception { ChannelPipeline pipeline = ch.pipeline(); // 添加处理器 pipeline.addLast(new MyServerHandler()); } }); // 绑定端口,开始接收进来的连接 ChannelFuture f = b.bind(port).sync(); // 等待服务器 socket 关闭 。 // 在这个例子中,这不会发生,但你可以优雅地关闭你的服务器。 f.channel().closeFuture().sync(); } finally { // 优雅地关闭线程池 workerGroup.shutdownGracefully(); bossGroup.shutdownGracefully(); } ``` 2. 创建 ChannelInitializer,设置 ChannelPipeline。 ```java public class MyServerHandler extends ChannelInboundHandlerAdapter { @Override public void channelRead(ChannelHandlerContext ctx, Object msg) { // 处理消息 ByteBuf in = (ByteBuf) msg; System.out.println(in.toString(CharsetUtil.UTF_8)); // 响应客户端 ctx.write(in); } @Override public void channelReadComplete(ChannelHandlerContext ctx) { // 刷新缓冲区 ctx.flush(); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { // 异常处理 cause.printStackTrace(); ctx.close(); } } ``` 3. 在 ChannelInitializer 中添加自定义的处理器,例如 MyServerHandler。 ```java public class MyServerHandler extends ChannelInboundHandlerAdapter { @Override public void channelRead(ChannelHandlerContext ctx, Object msg) { // 处理消息 ByteBuf in = (ByteBuf) msg; System.out.println(in.toString(CharsetUtil.UTF_8)); // 响应客户端 ctx.write(in); } @Override public void channelReadComplete(ChannelHandlerContext ctx) { // 刷新缓冲区 ctx.flush(); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { // 异常处理 cause.printStackTrace(); ctx.close(); } } ``` 4. 编写客户端程序,连接到服务端。 ```java EventLoopGroup group = new NioEventLoopGroup(); try { Bootstrap b = new Bootstrap(); b.group(group) .channel(NioSocketChannel.class) .option(ChannelOption.TCP_NODELAY, true) .handler(new ChannelInitializer<SocketChannel>() { @Override public void initChannel(SocketChannel ch) throws Exception { ChannelPipeline pipeline = ch.pipeline(); // 添加处理器 pipeline.addLast(new MyClientHandler()); } }); // 连接服务器 ChannelFuture f = b.connect(host, port).sync(); // 发送消息 ByteBuf buf = Unpooled.copiedBuffer("Hello, world!", CharsetUtil.UTF_8); f.channel().writeAndFlush(buf); // 等待直到连接关闭 f.channel().closeFuture().sync(); } finally { // 优雅地关闭线程池 group.shutdownGracefully(); } ``` 这样,就可以使用 Netty 编写一个 Socket 服务端实现和多个客户端通信

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值