基于netty的websocket在线聊天工具
netty和websocket在这里就不做过多的说明了
废话不多说,直接上代码
1 启动类
public class Main {
public static void main(String[] args) {
new ChatServer(Integer.valueOf(8222)).start();
}
}
2 Netty
public class ChatServer implements Runnable {
private final int port;
public ChatServer(int port) {
this.port = port;
}
public void start() {
new Thread(this, "imWebSocketThread").start();
}
@Override
public void run() {
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class)
.childHandler(new ChatServerInitializer());
try {
b.bind(port).sync().channel().closeFuture().sync();
} catch (InterruptedException e) {
e.printStackTrace();
}
} finally {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
}
public class ChatServerInitializer extends ChannelInitializer<SocketChannel> {
public ChatServerInitializer() {
super();
}
@Override
public void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast(new HttpServerCodec());
pipeline.addLast(new ChunkedWriteHandler());
pipeline.addLast(new HttpObjectAggregator(64 * 1024));
pipeline.addLast(new HttpRequestHandler("/imSocket"));
pipeline.addLast(new WebSocketServerProtocolHandler("/imSocket"));
pipeline.addLast(new WebSocketFrameHandler());
}
}
此处需注意,若需要支持https需要做如下处理
public class ChatServerInitializer extends ChannelInitializer<SocketChannel> {
public ChatServerInitializer() {
super();
}
@Override
public void initChannel(SocketChannel ch) throws Exception {
// SSL证书+密码
SSLContext context = getSSLContext("JKS", "D:/keystore.jks", "password");
SSLEngine engine = context.createSSLEngine();
engine.setUseClientMode(false);
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast(new SslHandler(engine));
pipeline.addLast(new HttpServerCodec());
pipeline.addLast(new ChunkedWriteHandler());
pipeline.addLast(new HttpObjectAggregator(64 * 1024));
pipeline.addLast(new HttpRequestHandler("/imSocket"));
pipeline.addLast(new WebSocketServerProtocolHandler("/imSocket"));
pipeline.addLast(new WebSocketFrameHandler());
}
private SSLContext getSSLContext(String type, String sslFile, String password) throws Exception {
try (
InputStream ksInputStream = new FileInputStream(sslFile);
) {
KeyStore kstore = KeyStore.getInstance(type);
kstore.load(ksInputStream, password.toCharArray());
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(kstore, password.toCharArray());
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(kmf.getKeyManagers(), null, null);
return sslContext;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
处理类
public class HttpRequestHandler extends SimpleChannelInboundHandler<FullHttpRequest> {
private final String uri;
public HttpRequestHandler(String uri) {
super();
this.uri = uri;
}
@Override
protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest msg) throws Exception {
if (uri.equalsIgnoreCase(msg.uri())) {
ctx.fireChannelRead(msg.retain());
}
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable e) throws Exception {
ctx.close();
e.printStackTrace();
}
}
public class WebSocketFrameHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {
@Override
public void userEventTriggered(ChannelHandlerContext ctx, Object obj) throws Exception {
try {
if(!(obj instanceof WebSocketServerProtocolHandler.ServerHandshakeStateEvent)) {
return;
}
WebSocketServerProtocolHandler.ServerHandshakeStateEvent.valueOf(obj.toString());
ctx.pipeline().remove(HttpRequestHandler.class);
String msg = ctx.channel().toString();
sendMsg(ctx.channel(), msg + "连接成功");
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) throws Exception {
sendMsg(ctx.channel(), "收到消息:"+msg.text());
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable e) throws Exception {
ctx.close();
e.printStackTrace();
}
public static boolean sendMsg(Channel channel, String message) {
try {
if(channel.isOpen()) {
return channel.writeAndFlush(new TextWebSocketFrame(message)).isSuccess();
} else {
channel.close();
return false;
}
} catch (Exception e) {
e.printStackTrace();
channel.close();
return false;
}
}
}
到此服务端就完成了
如果需要群聊可以通过ChannelGroup实现