Netty入门使用教程

更新时间:2023-05-12 02:37:05 阅读: 评论:0

Netty⼊门使⽤教程
原创:转载需注明原创地址
本⽂介绍Netty的使⽤, 结合我本⼈的⼀些理解和操作来快速的让初学者⼊门Netty, 理论知识会有, 但是不会太深⼊, 够⽤即可, 仅供⼊门! 需要想详细的知识可以移步Netty官⽹查看官⽅⽂档!
理论知识 : Netty提供异步的、事件驱动的⽹络应⽤程序框架和⼯具,⽤以快速开发⾼性能、⾼可靠性的⽹络服务器和客户端程序
当然, 我们这⾥主要是⽤Netty来发送消息, 接收消息, 测试⼀下demo, 更厉害的功能后⾯再慢慢发掘, 我们先看看这玩意怎么玩, 后⾯再深⼊
需要⼯具和Java类:
  netty-4.1.43
  netty服务器类      SayHelloServer.java
  netty服务端处理器类   SayHelloServerHandler.java
  netty客户端类      SayHelloClient.java
  netty客户端处理器类   SayHelloClientHandler.java
  服务器main⽅法测试类  MainNettyServer.java
  客户端main⽅法测试类  MainNettyClient.java
⾸先先来⼀张演⽰图, 最下⾯也会放:
我们看完以下部分就能实现这个东西了!
话不多说, 先贴代码:
package netty.rver;
bootstrap.ServerBootstrap;
channel.ChannelFuture;
channel.ChannelInitializer;
channel.ChannelOption;
channel.EventLoopGroup;
channel.nio.NioEventLoopGroup;
channel.socket.SocketChannel;
channel.socket.nio.NioServerSocketChannel;
import netty.handler.SayHelloServerHandler;
/**
* sayhello 服务器
*/
public class SayHelloServer {
/**
* 端⼝
*/
private int port ;
public SayHelloServer(int port){
this.port = port;
}
public void run() throws Exception{
/**
* Netty 负责装领导的事件处理线程池
*/
EventLoopGroup leader = new NioEventLoopGroup();
/
**
* Netty 负责装码农的事件处理线程池
*/
EventLoopGroup coder = new NioEventLoopGroup();
try {
/**
* 服务端启动引导器
*/
ServerBootstrap rver = new ServerBootstrap();
rver
.group(leader, coder)//把事件处理线程池添加进启动引导器
.
channel(NioServerSocketChannel.class)//设置通道的建⽴⽅式,这⾥采⽤Nio的通道⽅式来建⽴请求连接
.childHandler(new ChannelInitializer<SocketChannel>() {
//构造⼀个由通道处理器构成的通道管道流⽔线
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
/**
* 此处添加服务端的通道处理器
*/
socketChannel.pipeline().addLast(new SayHelloServerHandler());
}
})
/**
* ⽤来配置⼀些channel的参数,配置的参数会被ChannelConfig使⽤
* BACKLOG⽤于构造服务端套接字ServerSocket对象,
* 标识当服务器请求处理线程全满时,
* ⽤于临时存放已完成三次握⼿的请求的队列的最⼤长度。
* 如果未设置或所设置的值⼩于1,Java将使⽤默认值50
*/
.option(ChannelOption.SO_BACKLOG, 128)
/**
* 是否启⽤⼼跳保活机制。在双⽅TCP套接字建⽴连接后(即都进⼊ESTABLISHED状态)
* 并且在两个⼩时左右上层没有任何数据传输的情况下,这套机制才会被激活。
*/
.childOption(ChannelOption.SO_KEEPALIVE, true);
/**
* 服务端绑定端⼝并且开始接收进来的连接请求
*/
ChannelFuture channelFuture = rver.bind(port).sync();
/**
* 查看⼀下操作是不是成功结束了
*/
if (channelFuture.isSuccess()){
//如果没有成功结束就处理⼀些事情,结束了就执⾏关闭服务端等操作
System.out.println("服务端启动成功!");
}
/**
* 关闭服务端
*/
channelFuture.channel().cloFuture().sync();
System.out.println("服务端即将关闭!");
} finally {
/**
* 关闭事件处理组
*/
leader.shutdownGracefully();
coder.shutdownGracefully();
System.out.println("服务端已关闭!");
}
}
}
package netty.handler;
buffer.ByteBuf;
buffer.Unpooled;
channel.ChannelHandlerContext;
channel.ChannelInboundHandlerAdapter;
util.ChartUtil;
/**
* 服务端⼊站处理器适配器的继承类
* ⽤来处理服务端的⼀些事情
* 根据需要来实现⼀些⽅法
*/
public class SayHelloServerHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
ByteBuf buf = (ByteBuf) msg;
System.out.println("直接打印服务端需要处理的信息: " + String(ChartUtil.UTF_8));
ByteBuf res = Unpooled.wrappedBuffer(new String("塔台收到!塔台收到!信息如下, 请确认 " + String(ChartUtil.UTF_8)).getBytes());
/**
* 给客户端回复消息
*/
ctx.writeAndFlush(res);
}
/**
* 连接成功后,⾃动执⾏该⽅法
* @param ctx
* @throws Exception
*/
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
System.out.println("服务器⾸次处理!");
/**
* 这种发送的消息格式是错误的!!!!!
* 消息格式必须是ByteBuf才⾏!!!!!
*/
ctx.writeAndFlush("Hello is rver !");
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cau) throws Exception {
/**
* 异常捕获
*/
cau.printStackTrace();
ctx.clo();
}
}
package netty.client;
bootstrap.Bootstrap;
channel.*;
channel.nio.NioEventLoopGroup;
channel.socket.SocketChannel;
channel.socket.nio.NioSocketChannel;
import netty.handler.SayHelloClientHandler;
/**
* sayhello 客户端
*/
public class SayHelloClient {
private int port;
private String host = "127.0.0.1";
private Channel channel;
public SayHelloClient(int port){
this.port = port;
}
/**
* 客户端运⾏⽅法
* @throws InterruptedException
*/
public void run() throws InterruptedException {
/**
* 负责装客户端的事件处理线程池
*/
EventLoopGroup clientWorker = new NioEventLoopGroup();
try {
/**
* netty客户端引导启动器
*/
Bootstrap bootstrap = new Bootstrap();
bootstrap
.group(clientWorker)//把事件处理线程池添加进启动引导器
.channel(NioSocketChannel.class)//设置通道的建⽴⽅式,这⾥采⽤Nio的通道⽅式来建⽴请求连接                    //.option(ChannelOption.SO_KEEPALIVE, true)
.handler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
/**
* 此处添加客户端的通道处理器
*/
socketChannel.pipeline().addLast(new SayHelloClientHandler());
}
});
/**
* 客户端绑定端⼝并且开始发起连接请求
*/
ChannelFuture future = t(host, port).sync();
if (future.isSuccess()){
System.out.println("客户端连接服务器成功!");
}
/**
* 将通道设置好, 以便外⾯获取
*/
this.channel = future.channel();
/**
* 关闭客户端
*/
future.channel().cloFuture().sync();
System.out.println("客户端即将关闭!");
} finally {
/**
* 关闭事件处理组
*/
clientWorker.shutdownGracefully();
System.out.println("客户端已关闭!");
}
}
public Channel getChannel(){
return this.channel;
}
}
package netty.handler;
buffer.ByteBuf;
buffer.Unpooled;
channel.ChannelHandlerContext;
channel.ChannelInboundHandlerAdapter;
import java.nio.chart.Chart;
import java.util.Date;
/**
* sayhello 客户端处理器
*/
public class SayHelloClientHandler extends ChannelInboundHandlerAdapter {
/**
* 通道信息读取处理
* @param ctx
* @param msg
*/
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
ByteBuf m = (ByteBuf) msg; // 将消息转化成bytebuf
try {
System.out.println("客户端直接打印接收到的消息: " + m.toString(Chart.defaultChart()));
long currentTimeMillis = (m.readUnsignedInt() - 2208988800L) * 1000L;
System.out.println(new Date(currentTimeMillis));
/**
* 给服务端回复消息
*/
ctx.writeAndFlush("客户端收到! 消息为: " + m.toString(Chart.defaultChart()));
} finally {
}
}
/
**
* 连接成功后,⾃动执⾏该⽅法
* @param ctx
* @throws Exception
*/
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
/**
* 往服务端发送消息
* 消息格式必须是ByteBuf才⾏!!!!!
* 如果是其他格式服务端是接收不到的!!!!
*/
String helo = "你好呀!";
ByteBuf byteBuf = Unpooled.Bytes());
ctx.channel().writeAndFlush(byteBuf);
System.out.println("⾸次连接完成!");
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cau) {
cau.printStackTrace();
ctx.clo();
}
}
package netty;
import netty.rver.SayHelloServer;
/**
* Netty rver 使⽤main类
*/
public class MainNettyServer {
/**
* 端⼝
*/
private static int port = 8686;
public static void main(String[] args) throws Exception {
/**
* 启动netty服务器
*/
SayHelloServer sayHelloServer = new SayHelloServer(port);
sayHelloServer.run();
}
}
package netty;
buffer.ByteBuf;
buffer.Unpooled;
channel.Channel;
import netty.client.SayHelloClient;
import java.util.Scanner;
/**
* 客户端main⽅法类
*/
public class MainNettyClient {
public static void main(String[] args) throws InterruptedException {
/**
* 创建netty客户端
*/
SayHelloClient client = new SayHelloClient(8686);
/**
* 新建⼀个线程让它单独去跑,我们可以main⽅法测试⼀下发送消息和接受消息
*/
Thread clientThread = new Thread(new Runnable() {
@Override
public void run() {
try {
client.run();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
clientThread.start();
/**
* 如果不新建⼀个线程去跑客户端的话, 以下的代码就执⾏不到
* 这⾥⽤while是因为客户端的channel并不能⽴马⽣成, 会在client启动后⼀段时间才⽣成获取到
* 所以需要延迟⼀点获取channel, 否则channel为null
*/
Channel channel = null;
boolean isStart = fal;
while (!isStart) {
if (null != Channel()) {
channel = Channel();
isStart = true;
}
}
String helo = "你好呀!我这⾥是客户端, 收到请回答";
ByteBuf byteBuf = Unpooled.Bytes());
channel.writeAndFlush(byteBuf);
/**
* 我们通过控制台输⼊来给服务端发送消息
* 此处只做模拟使⽤
*/
for (int i = 0; i < 10 ; i++) {
Scanner scanner = new Scanner(System.in);
String text = Line();
channel.writeAndFlush(Unpooled.Bytes()));
}
}
}
接下来我们来使⽤⼀下看看, 我们⽤客户端控制台输⼊消息和服务端"对话": (gif录制软件-->ScreenToGif)⾸先我们把项⽬打包成jar包, 步骤如下:(eclip的⾃⾏百度, 此处⽤的是IDEA)

本文发布于:2023-05-12 02:37:05,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/fan/89/885944.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:消息   服务端   客户端   通道   处理   请求
相关文章
留言与评论(共有 0 条评论)
   
验证码:
推荐文章
排行榜
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图