由于在公司闲的蛋疼,看到Nio比较diao,所以开始学习起来,先实现一个简单的demo。
使用maven进行项目管理,依赖如下
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.gee</groupId>
<artifactId>my-netty</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.16.Final</version>
</dependency>
<!-- 时间工具类 start -->
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>2.9</version>
</dependency>
</dependencies>
<build>
<plugins>
<!-- 指定maven编译的jdk的版本 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</build>
</project>
工程目录如下
工程项目结构
那么动手来先构建服务端
config连接配置,配置如下
package config;
public class ConnectConfig {
private static final String host = "127.0.0.1";
private static final int port = 9527;
private static final int SO_BACKLOG = 1024;
public static int getPort() {
return port;
}
public static String getHost() {
return host;
}
public static int getSoBacklog() {
return SO_BACKLOG;
}
}
server
(一)服务的启动类
package server;
import config.ConnectConfig;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import server.handler.TimeServerChannelHandler;
public class TimeServer {
public static void main(String arg[]) {
//启动服务类
startServer();
}
private static void startServer() {
//用于处理accept事件
EventLoopGroup boss = new NioEventLoopGroup();
//用于处理通道的读写事件
EventLoopGroup work = new NioEventLoopGroup();
ServerBootstrap sb = new ServerBootstrap();
//主线程其实就是serverSocket,这里使用的是Nio,所以需要指定类型为NioServerSocketChannel
//childHandler,其实自己定义如何处理,服务端这边的通道
sb.group(boss, work).option(ChannelOption.SO_BACKLOG, ConnectConfig.getSoBacklog())
.channel(NioServerSocketChannel.class).childHandler(new TimeServerChannelHandler());
ChannelFuture cf = null;
try {
//服务端绑定端口,直到绑定成功,会一直阻塞
cf = sb.bind(ConnectConfig.getPort()).sync();
//服务端的主通道,直到等到关闭,会一直阻塞
cf.channel().closeFuture().sync();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
//将对应的监听线程关闭,避免线程没有杀死
boss.shutdownGracefully();
work.shutdownGracefully();
}
}
}
(二)服务的对于子通道的处理器
package client.handler;
import client.handler.adapter.TimeClientChannelHandlerAdapter;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.socket.SocketChannel;
public class TimeClientHandler extends ChannelInitializer<SocketChannel>{
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(new TimeClientChannelHandlerAdapter());
}
}
(三)服务的对于子通道的处理器适配器
package client.handler.adapter;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
public class TimeClientChannelHandlerAdapter extends ChannelInboundHandlerAdapter{
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
String req = "what time it is";
ctx.writeAndFlush(Unpooled.copiedBuffer(req.getBytes()));
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
ByteBuf req = (ByteBuf) msg;
byte[] reqinfo = new byte[req.readableBytes()];
req.readBytes(reqinfo);
System.out.println("now is " + new String(reqinfo, "UTF-8"));
}
}
那么动手来先构建客户端
(一)客户端的启动类
package client;
import client.handler.TimeClientHandler;
import config.ConnectConfig;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
public class TimeClient {
public static void main(String args[]) {
connect();
}
private static void connect() {
//用于客户端处通道的读写
EventLoopGroup work = new NioEventLoopGroup();
Bootstrap b = new Bootstrap();
b.group(work).option(ChannelOption.TCP_NODELAY, true).channel(NioSocketChannel.class)
.handler(new TimeClientHandler());
ChannelFuture cf = null;
try {
//一直阻塞,直到连接上服务端
cf = b.connect(ConnectConfig.getHost(), ConnectConfig.getPort()).sync();
//一直阻塞,直到该通道关闭
cf.channel().closeFuture().sync();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
//避免线程没有杀死
work.shutdownGracefully();
}
}
}
(二)客户端的对于通道的处理器
package client.handler;
import client.handler.adapter.TimeClientChannelHandlerAdapter;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.socket.SocketChannel;
public class TimeClientHandler extends ChannelInitializer<SocketChannel>{
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(new TimeClientChannelHandlerAdapter());
}
}
(三)客户端的对于通道的处理器适配器
package client.handler.adapter;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
public class TimeClientChannelHandlerAdapter extends ChannelInboundHandlerAdapter{
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
String req = "what time it is";
ctx.writeAndFlush(Unpooled.copiedBuffer(req.getBytes()));
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
ByteBuf req = (ByteBuf) msg;
byte[] reqinfo = new byte[req.readableBytes()];
req.readBytes(reqinfo);
System.out.println("now is " + new String(reqinfo, "UTF-8"));
}
}
最后运行,结果如下
服务端收到来自客户端的请求:what time it is
客户端得到服务端的响应:now is 2021-02-18T10:41:30.068+08:00
服务端
客户端
网友评论