實現(xiàn)以下功能:
1开缎,一個客戶端上線/下線,通知所有的用戶林螃。
2奕删,一個客戶端發(fā)送消息,廣播所有的客戶端疗认。
server端代碼
- 1完残,Server.java
public class Server {
public static void main(String... arg) throws Exception {
//負責(zé)接收客戶端連接
NioEventLoopGroup boss = new NioEventLoopGroup();
//負責(zé)處理客戶端連接
NioEventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap.group(boss, workerGroup)
.channel(NioServerSocketChannel.class)
.handler(new LoggingHandler(LogLevel.INFO))
.childHandler(new ServerChatinitlizer());
//綁定端口號
ChannelFuture channelFuture = bootstrap.bind(8899).sync();
channelFuture.channel().closeFuture().sync();
} finally {
boss.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
}
- 2,ServerChatinitlizer.java
public class ServerChatinitlizer extends ChannelInitializer<SocketChannel> {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
//編碼解碼器
// 換行分割解碼器 \r\n
pipeline.addLast(new DelimiterBasedFrameDecoder(4096, Delimiters.lineDelimiter()));
pipeline.addLast(new StringDecoder(CharsetUtil.UTF_8));
pipeline.addLast(new StringEncoder(CharsetUtil.UTF_8));
//自己的處理器
pipeline.addLast(new ServerChatHandler());
}
}
- 3,ServerChatHandler.java
/**
* 客戶端上線/下線 提示所有的人
* 發(fā)送消息發(fā)給所有的人
*/
public class ServerChatHandler extends SimpleChannelInboundHandler<String> {
//保存已建立所用用戶的實例
private static ChannelGroup channelGroup = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
//接收客戶端發(fā)送的消息
@Override
protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
Channel channel = ctx.channel();
channelGroup.forEach(ch -> {
if (ch == channel) { //表示自己
channel.writeAndFlush("[自己] " + msg + "\n");
} else {
ch.writeAndFlush(ch.remoteAddress() + " 發(fā)送的消息 " + msg + "\n");
}
});
}
//客戶端與服務(wù)器端建立好連接
@Override
public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
System.out.println("handlerAdded");
Channel channel = ctx.channel();
//廣播已連接的客戶端 有新的用戶上線
channelGroup.writeAndFlush("[服務(wù)器]-" + channel.remoteAddress() +" 上線\n");
// 保存用戶實例
channelGroup.add(channel);
}
//鏈接斷開
@Override
public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
System.out.println("handlerRemoved");
Channel channel = ctx.channel();
//廣播已連接的客戶端 用戶下線
channelGroup.writeAndFlush("[服務(wù)器]-" + channel.remoteAddress() + " 下線\n");
//channelGroup 會自動 剔除已斷開的用戶連接
}
//處于活動狀態(tài)
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
Channel channel = ctx.channel();
System.out.println("[服務(wù)器]-" + channel.remoteAddress() +" 上線\n");
}
//下線
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
super.channelInactive(ctx);
Channel channel = ctx.channel();
System.out.println("[服務(wù)器]-" + channel.remoteAddress() + " 下線\n");
}
// 發(fā)生異常關(guān)閉連接
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
cause.printStackTrace();
ctx.close();
}
}
client端代碼
- 1,Client.java
public class Client {
public static void main(String... arg) throws Exception {
EventLoopGroup eventLoopGroup = new NioEventLoopGroup();
try {
Bootstrap bootstrap = new Bootstrap();
bootstrap.group(eventLoopGroup).channel(NioSocketChannel.class)
.handler(new ChatInitializer());
Channel channel = bootstrap.connect("127.0.0.1",8899).sync().channel();
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
while (true){
channel.writeAndFlush(br.readLine()+"\r\n");
}
} finally {
eventLoopGroup.shutdownGracefully();
}
}
}
- 2, ChatInitializer.java
public class ChatInitializer extends ChannelInitializer<SocketChannel> {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast(new DelimiterBasedFrameDecoder(4096, Delimiters.lineDelimiter()));
pipeline.addLast(new StringEncoder(CharsetUtil.UTF_8));
pipeline.addLast(new StringDecoder(CharsetUtil.UTF_8));
pipeline.addLast(new ChatHandler());
}
}
- 3, ChatHandler
public class ChatHandler extends SimpleChannelInboundHandler<String> {
@Override
protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
System.out.println(" 接收到數(shù)據(jù) " + msg);
}
}