1)服务端
ChatServer.java
package chat;
import chat.handler.WSServerInitializer;
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;
public class ChatServer {
public static void main(String[] args) {
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap serverBootstrap = new ServerBootstrap();
serverBootstrap.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new WSServerInitializer());
int port = 8088;
ChannelFuture channelFuture = serverBootstrap.bind(port).sync();
System.out.println("聊天服务器启动成功 port:" + port);
channelFuture.channel().closeFuture().sync();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
}
2)WSServerInitializer.java
package chat.handler;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
import io.netty.handler.stream.ChunkedWriteHandler;
public class WSServerInitializer extends ChannelInitializer<SocketChannel> {
protected void initChannel(SocketChannel socketChannel) throws Exception {
ChannelPipeline pipeline = socketChannel.pipeline();
pipeline.addLast(new HttpServerCodec());
pipeline.addLast(new ChunkedWriteHandler());
pipeline.addLast(new HttpObjectAggregator(1024 * 64));
pipeline.addLast(new WebSocketServerProtocolHandler("/ws"));
// 业务Handler
pipeline.addLast(new ChatHandler());
}
}
3)ChatHandler.java
package chat.handler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import java.time.LocalDateTime;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class ChatHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {
// 存储所有的客户端
private static ConcurrentHashMap<ChannelHandlerContext, ChannelHandlerContext> clientHashMap = new ConcurrentHashMap<>();
protected void channelRead0(ChannelHandlerContext channelHandlerContext, TextWebSocketFrame textWebSocketFrame) throws Exception {
String content = textWebSocketFrame.text();
for (ChannelHandlerContext key : clientHashMap.keySet()) {
ChannelHandlerContext ctx = key;
ctx.channel().writeAndFlush(new TextWebSocketFrame(LocalDateTime.now() + " " + channelHandlerContext.channel().remoteAddress() + "说: " + content));
}
}
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
System.out.println("客户端进来了:" + ctx.channel().remoteAddress());
clientHashMap.put(ctx, ctx);
}
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
System.out.println("客户端断开连接:" + ctx.channel().remoteAddress());
clientHashMap.remove(ctx);
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
System.out.println("客户端异常:" + ctx.channel().remoteAddress());
cause.printStackTrace();
ctx.close();
}
}
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<!--设置包名和版本号-->
<artifactId>NettyChatRoom</artifactId>
<version>1.0</version>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<!--设置java版本-->
<configuration>
<source>8</source>
<target>8</target>
</configuration>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.3.0</version>
<configuration>
<!--设置入口类-->
<archive>
<manifest>
<mainClass>chat.ChatServer</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<!--去掉打包后缀-->
<appendAssemblyId>false</appendAssemblyId>
</configuration>
<executions>
<execution>
<id>make-assembly</id> <!-- this is used for inheritance merges -->
<phase>package</phase> <!-- bind to the packaging phase -->
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.32.Final</version>
</dependency>
</dependencies>
</project>
2)客户端
ChatClient.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title></title>
</head>
<body>
<div>发送消息:</div>
<input type="text" id="msgContent"/>
<input type="button" value="点我发送" onclick="CHAT.chat()"/>
<div>接受消息:</div>
<div id="receiveMsg" style="background-color: gainsboro;"></div>
<script type="application/javascript">
window.CHAT = {
socket: null,
init: function () {
if (window.WebSocket) {
CHAT.socket = new WebSocket("ws://127.0.0.1:8088/ws");
CHAT.socket.onopen = function () {
console.log("连接建立成功...");
};
CHAT.socket.onclose = function () {
console.log("连接关闭...");
};
CHAT.socket.onerror = function () {
};
CHAT.socket.onmessage = function (e) {
console.log("接收到消息" + e.data);
var receiveMsg = document.getElementById("receiveMsg");
var html = receiveMsg.innerHTML;
receiveMsg.innerHTML = html + "</br>" + e.data;
};
} else {
alert("浏览器不支持websocket协议...");
}
},
/**
* 发送消息
*/
chat: function () {
var msg = document.getElementById("msgContent");
CHAT.socket.send(msg.value);
}
};
CHAT.init();
</script>
</body>
</html>
来源:oschina
链接:https://my.oschina.net/u/4354143/blog/4839569