前言
以前一直对通讯这块不是很了解 最新学习了一下netty 搞了个简易的聊天室
为自己7秒的记忆 留下火种
准备
<!-- netty包 -->
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.26.Final</version>
</dependency>
服务端代码
1.服务器启动主方法
package netty.server;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import netty.server.init.NettyServerIniter;
/**
* @author zth
*
*/
public class NettyServer {
//netty服务端监听的端口
private static int NETTY_SERVER_PORT=9999;
public static void main(String[] args) {
EventLoopGroup group = null;
try {
//创建服务端
ServerBootstrap server = new ServerBootstrap();
//使用nio方式
group = new NioEventLoopGroup();
server.group(group);
//类似serversocket吧?
server.channel(NioServerSocketChannel.class);
//初始化处理器
server.childHandler(new NettyServerIniter());
//绑定端口
ChannelFuture channelFuture = server.bind(NETTY_SERVER_PORT).sync();
System.out.println("netty 服务端 启动成功");
channelFuture.channel().closeFuture().sync();
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
//关闭回收线程
group.shutdownGracefully();
}
}
}
2.频道初始化
package netty.server.init;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.DelimiterBasedFrameDecoder;
import io.netty.handler.codec.Delimiters;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import netty.server.handle.NettyServerHandler;
/**
* @author zth
*
*/
public class NettyServerIniter extends ChannelInitializer<SocketChannel>{
@Override
protected void initChannel(SocketChannel channel) throws Exception {
ChannelPipeline pipeline = channel.pipeline();
//采用分隔符解码器
pipeline.addLast("framer",new DelimiterBasedFrameDecoder(1024, Delimiters.lineDelimiter()));
//字符串解码
pipeline.addLast("decoder",new StringDecoder());
//字符创编码
pipeline.addLast("encoder",new StringEncoder());
//自定义处理器
pipeline.addLast("handler",new NettyServerHandler());
}
}
3.自定义处理器
package netty.server.handle;
import java.net.InetAddress;
import java.util.Date;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.util.concurrent.GlobalEventExecutor;
/**
* @author zth
*
*/
public class NettyServerHandler extends SimpleChannelInboundHandler<String>{
//频道组 用来加入客户端频道进行广播
private static final ChannelGroup CHANNEL_GROUP = new DefaultChannelGroup("ChannelGroups", GlobalEventExecutor.INSTANCE);
//退出编码
private static String exit_code = "exit";
@Override
protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
System.out.println("服务端接收消息:"+msg);
if(exit_code.equals(msg)) {
System.out.println("关闭服务端");
ctx.close();
}
Date date = new Date();
String returnMsg = date.toLocaleString()+":"+msg+"\n";
//单体回复消息客户端
// ctx.writeAndFlush("回复:"+returnMsg);
//广播所有客户端
Channel ch = ctx.channel();
CHANNEL_GROUP.add(ch);
CHANNEL_GROUP.writeAndFlush("广播:"+returnMsg);
}
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
System.out.println("连接客户端:"+ctx.channel().remoteAddress());
String returnStr = "客户端 成功 与服务端"+InetAddress.getLocalHost().getHostName()+"建立连接\n";
ctx.writeAndFlush(returnStr);
super.channelActive(ctx);
}
}
客户端代码
1.客户端主程序
package netty.client;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
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.NioSocketChannel;
import io.netty.handler.codec.DelimiterBasedFrameDecoder;
import io.netty.handler.codec.Delimiters;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import netty.client.handler.NettyClientHandler;
/**
* @author zth
*
*/
public class NettyClient2 {
//服务端地址
private static String netty_server_host = "127.0.0.1";
//服务端端口
private static int netty_server_port = 9999;
public static void main(String[] args) throws InterruptedException, IOException {
//netty客户端
Bootstrap client = new Bootstrap();
//采用nio
EventLoopGroup group = new NioEventLoopGroup();
client.group(group);
client.channel(NioSocketChannel.class);
//处理器设置
client.handler(new ChannelInitializer<SocketChannel>() {
//初始化处理器设置
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pie = ch.pipeline();
pie.addLast("framer",new DelimiterBasedFrameDecoder(1024, Delimiters.lineDelimiter()));
pie.addLast("decoder",new StringDecoder());
pie.addLast("encoder",new StringEncoder());
//自定义处理器
pie.addLast(new NettyClientHandler());
}
});
//连接服务端
Channel channel = client.connect(netty_server_host, netty_server_port).sync().channel();
//加入消息
String startMsg = "client2加入了聊天\n";
channel.writeAndFlush(startMsg);
//模拟聊天……
while (true) {
System.out.println("请输入想要发送的消息:");
InputStreamReader in = new InputStreamReader(System.in);
BufferedReader reader = new BufferedReader(in);
String msg = reader.readLine()+"\r\n";
// System.out.println("客户端发送消息:"+msg);
channel.writeAndFlush(msg);
}
}
}
2.自定义处理器
package netty.client.handler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
/**
* @author zth
*
*/
public class NettyClientHandler extends SimpleChannelInboundHandler<String>{
@Override
protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
System.out.println("22222接收到服务端消息:"+msg);
}
}
完成 可以多复制几个客户端 开启来 通过广播把消息传给每一个客户端
还有很多功能没做 比如传图片,聊天记录,表情包什么的
可以通过文件服务器oss 数据什么的来完成