使用netty实现客户端和服务端的通信
记录学习netty的简单代码
1.新建springboot项目,可访问https://spring.io/创建下载项目
2.导入开发工具,并添加netty jar包
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
</dependency>
3.编写服务端类
package com.example.study.netty;
import javax.annotation.PostConstruct;
import org.springframework.stereotype.Component;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
@Component
public class Server {
private ServerBootstrap serverBootstrap = new ServerBootstrap();
private EventLoopGroup bossGroup = new NioEventLoopGroup();
private EventLoopGroup workerGroup = new NioEventLoopGroup();
private ChannelFuture cf;
@PostConstruct
private void init() {
new Thread(new Runnable() {
@Override
public void run() {
System.err.println("start thread");
try {
runServer();
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
private void runServer() {
try {
serverBootstrap.group(bossGroup, workerGroup);
serverBootstrap.channel(NioServerSocketChannel.class).childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast(new ServerHandler());
}
});
cf = serverBootstrap.bind(10088).sync();
cf.channel().closeFuture().sync();
} catch (Exception e) {
e.printStackTrace();
} finally {
workerGroup.shutdownGracefully();
bossGroup.shutdownGracefully();
}
}
}
编写服务端处理类ServerHandler需继承ChannelInboundHandlerAdapter
package com.example.study.netty;
import java.net.InetSocketAddress;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
public class ServerHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
// 连接时执行此方法
System.err.println("开始执行channelActive.......");
}
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
// 连接关闭时执行此方法
System.err.println("开始执行channelInactive.......");
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
// do something msg
InetSocketAddress insocket = (InetSocketAddress) ctx.channel().remoteAddress();
String clientIp = insocket.getAddress().getHostAddress();
Integer port = insocket.getPort();
ByteBuf buf = (ByteBuf) msg;
byte[] data = new byte[buf.readableBytes()];
buf.readBytes(data);
String request = new String(data, "utf-8");
System.out.println("Server: " + request + "--" + clientIp + ":" + port);
// 写给客户端
String response = "我是反馈的信息";
ctx.writeAndFlush(Unpooled.copiedBuffer("888".getBytes()));
}
@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
System.err.println("开始执行channelReadComplete.......");
}
@Override
public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
// TODO Auto-generated method stub
super.channelRegistered(ctx);
}
@Override
public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
// TODO Auto-generated method stub
super.channelUnregistered(ctx);
}
@Override
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
// TODO Auto-generated method stub
super.userEventTriggered(ctx, evt);
}
@Override
public void channelWritabilityChanged(ChannelHandlerContext ctx) throws Exception {
// TODO Auto-generated method stub
super.channelWritabilityChanged(ctx);
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
// TODO Auto-generated method stub
super.exceptionCaught(ctx, cause);
}
}
启动项目即可开始netty服务端对10088端口进行监控
4.编写客户端类
public class Client {
public static void main(String[] args) {
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
Bootstrap bootstrap = new Bootstrap();
bootstrap.group(workerGroup).channel(NioSocketChannel.class)
.handler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast(new ClientHandler());
}
});
ChannelFuture cFuture = bootstrap.connect("127.0.0.1", 10088).sync();
cFuture.channel().writeAndFlush(Unpooled.copiedBuffer("123".getBytes()));
cFuture.channel().closeFuture().sync();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
workerGroup.shutdownGracefully();
}
}
}
编写客户端处理类ClientHandler需继承ChannelInboundHandlerAdapter
package com.example.study.netty;
import java.net.InetSocketAddress;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.codec.http.DefaultFullHttpResponse;
import io.netty.handler.codec.http.FullHttpResponse;
import io.netty.handler.codec.http.HttpHeaderNames;
import io.netty.handler.codec.http.HttpRequest;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.handler.codec.http.HttpVersion;
import io.netty.util.CharsetUtil;
import io.netty.util.ReferenceCountUtil;
public class ClientHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
// 获取channel
InetSocketAddress insocket = (InetSocketAddress) ctx.channel().remoteAddress();
String clientIp = insocket.getAddress().getHostAddress();
Integer port = insocket.getPort();
Channel channel = ctx.channel();
// 获取客户端传输过来的消息
try {
ByteBuf buf = (ByteBuf) msg;
byte[] data = new byte[buf.readableBytes()];
buf.readBytes(data);
System.out.println("Client:" + new String(data).trim());
// 向服务器写数据
ctx.writeAndFlush(Unpooled.copiedBuffer("555".getBytes()));
} finally {
ReferenceCountUtil.release(msg);
}
}
@Override
public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
// TODO Auto-generated method stub
super.channelRegistered(ctx);
}
@Override
public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
// TODO Auto-generated method stub
super.channelUnregistered(ctx);
}
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
// TODO Auto-generated method stub
super.channelActive(ctx);
}
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
// TODO Auto-generated method stub
super.channelInactive(ctx);
}
@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
// TODO Auto-generated method stub
super.channelReadComplete(ctx);
}
@Override
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
// TODO Auto-generated method stub
super.userEventTriggered(ctx, evt);
}
@Override
public void channelWritabilityChanged(ChannelHandlerContext ctx) throws Exception {
// TODO Auto-generated method stub
super.channelWritabilityChanged(ctx);
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
// TODO Auto-generated method stub
super.exceptionCaught(ctx, cause);
}
@Override
public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
// TODO Auto-generated method stub
super.handlerAdded(ctx);
}
@Override
public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
// TODO Auto-generated method stub
super.handlerRemoved(ctx);
}
}
运行client中main方法,即可实现通信