1.导包
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.36.Final</version>
</dependency>
<!-- io常用工具类 -->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.5</version>
</dependency>
<!-- 阿里JSON解析器 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.68</version>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.10</version>
</dependency>
2.编写启动类
import netty.NettyServer;
public class SocketService {
public static void main(String[] args) {
try {
new NettyServer(8089).start();
}catch(Exception e) {
System.out.println("NettyServerError:"+e.getMessage());
}
}
}
package netty;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
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 NettyServer {
private final int port;
public NettyServer(int port) {
this.port = port;
}
public void start() throws Exception {
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup group = new NioEventLoopGroup();
try {
ServerBootstrap sb = new ServerBootstrap();
sb.option(ChannelOption.SO_BACKLOG, 1024);
sb.group(group, bossGroup)
.channel(NioServerSocketChannel.class)
.localAddress(this.port)
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
System.out.println("收到新连接");
ch.pipeline().addLast(new HttpServerCodec());
ch.pipeline().addLast(new ChunkedWriteHandler());
ch.pipeline().addLast(new HttpObjectAggregator(8192));
ch.pipeline().addLast(new MyWebSocketHandler());
ch.pipeline().addLast(new WebSocketServerProtocolHandler("/dongwo", null, true, 65536 * 10));
}
});
ChannelFuture cf = sb.bind().sync();
System.out.println(NettyServer.class + " 启动正在监听: " + cf.channel().localAddress());
cf.channel().closeFuture().sync();
} finally {
group.shutdownGracefully().sync();
bossGroup.shutdownGracefully().sync();
}
}
}
package netty;
import java.util.concurrent.ConcurrentHashMap;
public class BiDirectionHashMap<K,V> {
private ConcurrentHashMap<K, V> k2v;
private ConcurrentHashMap<V, K> v2k;
BiDirectionHashMap() {
this.k2v = new ConcurrentHashMap<>();
this.v2k = new ConcurrentHashMap<>();
}
public void put(K k, V v) {
k2v.put(k, v);
v2k.put(v, k);
}
public int size () {
return k2v.size();
}
public boolean containsKey(K k) {
return k2v.containsKey(k);
}
public boolean containsValue(V v) {
return v2k.containsKey(v);
}
public boolean removeByKey(K k) {
if (!k2v.containsKey(k)) {
return false;
}
V value = k2v.get(k);
k2v.remove(k);
v2k.remove(value);
return true;
}
public boolean removeByValue(V v) {
if (!v2k.containsKey(v)) {
return false;
}
K key = v2k.get(v);
v2k.remove(v);
k2v.remove(key);
return true;
}
public V getByKey(K k) {
return k2v.getOrDefault(k, null);
}
public K getByValue(V v) {
return v2k.getOrDefault(v, null);
}
}
package netty;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.util.AttributeKey;
import io.netty.util.concurrent.GlobalEventExecutor;
import pojo.User;
public class MyChannelHandlerPool {
public static ChannelGroup channelGroup;
public static final String USER_INFO = "userInfo";
static {
channelGroup=new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
}
public static int i = 0;
public static int getOnlyNumsChannelGroup(){
return channelGroup.size();
}
public static void setChannelParameter(ChannelHandlerContext channelHandlerContext, String key, Object vaule){
channelHandlerContext.attr(AttributeKey.valueOf(key)).set(vaule);
}
public static void setChannelParameter(Channel channel, String key, Object vaule){
channel.attr(AttributeKey.valueOf(key)).set(vaule);
}
public static Object getChannelParameter(ChannelHandlerContext channelHandlerContext,String key){
return getChannelParameter(channelHandlerContext.channel(),key);
}
public static Object getChannelParameter(Channel channel,String key){
return channel.attr(AttributeKey.valueOf(key)).get();
}
public static void sendAllMessage(String message){
System.out.println("向所有客户端推送消息:"+message+"");
MyChannelHandlerPool.channelGroup.writeAndFlush( new TextWebSocketFrame(message));
}
public static void sendMessgae(String message, Long userId){
Channel channel = MyChanneMapManager.biDirectionHashMap.getByKey(userId);
if(channel!=null){
Object channelParameter = MyChannelHandlerPool.getChannelParameter(channel, MyChannelHandlerPool.USER_INFO);
User user = new User();
if(channelParameter!=null){
user = (User) channelParameter;
}
System.err.println("向["+user.getNickName()+"]推送消息:"+message+"");
channel.writeAndFlush( new TextWebSocketFrame(message));
}else{
System.err.println("推送用户不存在");
}
}
}
package netty;
import io.netty.channel.Channel;
public class MyChanneMapManager {
public static BiDirectionHashMap<Long, Channel> biDirectionHashMap = new BiDirectionHashMap<>();
public static boolean existConnectionByID (Long id) {
return biDirectionHashMap.containsKey(id);
}
}
package netty;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import pojo.User;
import utils.NetUtils;
import java.util.Map;
public class MyWebSocketHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
System.out.println("与客户端建立连接,通道开启!");
MyChannelHandlerPool.channelGroup.add(ctx.channel());
}
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
System.out.println("与客户端断开连接,通道关闭!");
MyChannelHandlerPool.channelGroup.remove(ctx.channel());
MyChanneMapManager.biDirectionHashMap.removeByValue(ctx.channel());
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
if (null != msg && msg instanceof FullHttpRequest) {
httpdoMessage(ctx,(FullHttpRequest)msg);
}else if(msg instanceof TextWebSocketFrame){
textdoMessage(ctx,(TextWebSocketFrame)msg);
}
super.channelRead(ctx, msg);
}
@Override
protected void channelRead0(ChannelHandlerContext channelHandlerContext, TextWebSocketFrame textWebSocketFrame) throws Exception {
}
private void textdoMessage(ChannelHandlerContext ctx, TextWebSocketFrame textWebSocketFrame){
JSONObject parse = JSONObject.parseObject(textWebSocketFrame.text());
System.out.println("后续webSocket参数:"+ parse);
}
protected void httpdoMessage(ChannelHandlerContext ctx, FullHttpRequest fullHttpRequest){
String uri = fullHttpRequest.uri();
Map paramMap= NetUtils.getUrlParams(uri);
System.out.println("首次http连接参数是:"+ JSON.toJSONString(paramMap));
long i = MyChannelHandlerPool.i;
User user = new User();
user.setId(i);
user.setNickName(i+"号用户");
MyChannelHandlerPool.setChannelParameter(ctx,MyChannelHandlerPool.USER_INFO,user);
if(!MyChanneMapManager.existConnectionByID(i)){
MyChanneMapManager.biDirectionHashMap.put(i,ctx.channel());
}
System.err.println("当前用户编号:"+i);
MyChannelHandlerPool.i++;
if(uri.contains("?")){
String newUri=uri.substring(0,uri.indexOf("?"));
System.out.println(newUri);
fullHttpRequest.setUri(newUri);
}
System.out.println("当前在线人数:"+MyChannelHandlerPool.getOnlyNumsChannelGroup()+";"+MyChanneMapManager.biDirectionHashMap.size());
}
}
package utils;
import java.util.HashMap;
import java.util.Map;
public class NetUtils {
public static Map getUrlParams(String url){
Map<String,String> map = new HashMap<String,String>();
url = url.replace("?",";");
if (!url.contains(";")){
return map;
}
if (url.split(";").length > 0){
String[] arr = url.split(";")[1].split("&");
for (String s : arr){
String key = s.split("=")[0];
String value = s.split("=")[1];
map.put(key,value);
}
return map;
}else{
return map;
}
}
}