使用netty实现一个简单的聊天功能
-
什么是netty
<1> Netty是由JBOSS提供的一个java开源框架。Netty提供异步的、事件驱动的网络应用程序框架和工具,用以快速开发高性能、高可靠性的网络服务器和客户端程序。
<2> Netty 是一个基于NIO的客户、服务器端编程框架,使用Netty 可以确保你快速和简单的开发出一个网络应用,例如实现了某种协议的客户、服务端应用。
<3> Netty是一个异步事件驱动的网络应用框架,用于快速开发可维护的高性能服务器和客户端。 -
特点: 快速开发高性能、高可靠性
-
Netty 官网地址: http://netty.io/
-
依赖的jar包:
netty-3.10.5.Final.jar
该jar包可以到Netty的官网上进行下载 -
环境: IDEA + JDK1.8 + netty-3.10.5
-
接下来我们书写代码实现最简单聊天的功能
注: 我们使用的是基础的方法,最好理解的方式实现 -
我们建立java项目并导入Netty包,项目结构如下图所示:
- 服务端代码
package com.wdhcr.netty;
import org.jboss.netty.bootstrap.ServerBootstrap;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.Channels;
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
import org.jboss.netty.handler.codec.string.StringDecoder;
import org.jboss.netty.handler.codec.string.StringEncoder;
import java.net.InetSocketAddress;
public class Server {
public static void main(String[] args) {
//创建服务端启动辅助类对象,他可以很方便的创建一个Netty服务端
ServerBootstrap serverBootstrap = new ServerBootstrap();
NioServerSocketChannelFactory nioServerSocketChannelFactory = new NioServerSocketChannelFactory();
//使netty服务端和nioServerSocketChannelFactory绑定
serverBootstrap.setFactory(nioServerSocketChannelFactory);
serverBootstrap.setPipelineFactory(()->{
//获取channelHandler的一个容器,负责管理和调用
ChannelPipeline pipeline = Channels.pipeline();
//增加处理器,增加传输中的编码,和解码处理器
pipeline.addLast("encoder", new StringEncoder());
pipeline.addLast("decoder", new StringDecoder());
//添加自定义处理器
pipeline.addLast("ServerHandler", new ServerHandler());
return pipeline;
});
//使用new对象的方式封装一个端口
//监听端口
serverBootstrap.bind(new InetSocketAddress(8888));
System.out.println("服务端开启成功!!");
}
}
- 服务端的自定义处理器类
package com.wdhcr.netty;
import org.jboss.netty.channel.*;
import java.util.Scanner;
public class ServerHandler extends SimpleChannelHandler {
@Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
System.out.println("客户端:" + e.getMessage());
//获取一个通道
Channel channel = ctx.getChannel();
//创建键盘录入对象
Scanner scanner = new Scanner(System.in);
System.out.println("服务端:");
String sData = scanner.next();
//当客户端有数据发送过来时,再响应发送
channel.write(sData);
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {
System.out.println("异常捕获!!");
}
@Override
public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
System.out.println("建立连接!!");
}
@Override
public void channelDisconnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
System.out.println("断开连接!!");
}
@Override
public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
System.out.println("关闭连接!!");
}
}
- 客户端的代码
package com.wdhcr.netty;
import org.jboss.netty.bootstrap.ClientBootstrap;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.Channels;
import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory;
import org.jboss.netty.handler.codec.string.StringDecoder;
import org.jboss.netty.handler.codec.string.StringEncoder;
import java.net.InetSocketAddress;
import java.util.Scanner;
public class Client {
public static void main(String[] args) {
//创建客户端启动辅助类对象,他可以很方便的创建一个Netty客户端
ClientBootstrap clientBootstrap = new ClientBootstrap();
NioClientSocketChannelFactory nioClientSocketChannelFactory = new NioClientSocketChannelFactory();
//设置客户端引导,让他和nioClientSocketChannelFactory绑定
clientBootstrap.setFactory(nioClientSocketChannelFactory);
clientBootstrap.setPipelineFactory(()->{
ChannelPipeline pipeline = Channels.pipeline();
//增加处理器,处理传输时的编码和解码
pipeline.addLast("encoder", new StringEncoder());
pipeline.addLast("decoder", new StringDecoder());
//自定义处理器
pipeline.addLast("ClientHandler", new ClientHandler());
return pipeline;
});
//InetSocketAddress类主要作用是封装端口,并且有构造方法,比InetAddress好用
InetSocketAddress socketAddress = new InetSocketAddress("localhost",8888);
ChannelFuture connect = clientBootstrap.connect(socketAddress);
Channel channel = connect.getChannel();
Scanner scanner = new Scanner(System.in);
System.out.println("客户端:");
while (true) {
String cData = scanner.next();
channel.write(cData);
}
}
}
- 客户端的自定义处理器代码:
package com.wdhcr.netty;
import org.jboss.netty.channel.*;
public class ClientHandler extends SimpleChannelHandler {
//这是处理接收和响应客户端的方法
@Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
System.out.println("服务端:"+e.getMessage());
//这个输出语句在这是,当服务端响应了以后再进行数据
System.out.println("客户端:");
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {
System.out.println("捕获异常");
}
@Override
public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
System.out.println("连接成功");
}
@Override
public void channelDisconnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
System.out.println("断开连接成功");
}
@Override
public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
System.out.println("关闭通道!!");
}
}
-
以上代码就实现了一个简单的聊天功能
-
注意: 运行时要先运行服务端的代码,然后运行客户端代码。
-
最后,如果还想更加深入了解,可在官网的API文档了解。