package org.springblade.common.handler; import com.alibaba.fastjson.JSONObject; import com.corundumstudio.socketio.*; import com.corundumstudio.socketio.annotation.OnConnect; import com.corundumstudio.socketio.annotation.OnDisconnect; import com.corundumstudio.socketio.annotation.OnEvent; import com.corundumstudio.socketio.protocol.Packet; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; import com.corundumstudio.socketio.SocketIOServer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; import java.net.ServerSocket; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.function.BiConsumer; /** * SocketIo启动类 */ @Component @Order(value = 1) public class SocketIOService { private final Logger log = LoggerFactory.getLogger(this.getClass()); // 用来存已连接的客户端 private static Map clientMap = new ConcurrentHashMap<>(); @Autowired private SocketIOServer socketIOServer; /** * Spring IoC容器创建之后,在加载SocketIOServiceImpl Bean之后启动 * * @throws Exception */ @PostConstruct private void autoStartup() throws Exception { log.info("启动Socket!!!!!!!!!!"); start(); } /** * Spring IoC容器在销毁SocketIOServiceImpl Bean之前关闭,避免重启项目服务端口占用问题 * * @throws Exception */ @PreDestroy private void autoStop() throws Exception { stop(); } public void start() { // 监听客户端连接 socketIOServer.addConnectListener(client -> { String uid = getParamsByClient(client); if (uid != null) { clientMap.put(uid, client); log.info("有新的客户端连接UID:{}", uid); } // 给客户端发送一条信息 发送ClientReceive事件 需要客户端绑定此事件即可接收到消息 JSONObject jsonObject = new JSONObject(); jsonObject.put("name", "goat"); jsonObject.put("message", "hello client"); client.sendEvent("ClientReceive", jsonObject); }); // 监听客户端断开连接 socketIOServer.addDisconnectListener(listener -> { String uid = getParamsByClient(listener); if (uid != null) { clientMap.remove(uid); listener.disconnect(); log.info("一条客户端连接中断"); } }); socketIOServer.addEventListener("ServerReceive", JSONObject.class, (client, data, ackSender) -> { String uid = getParamsByClient(client); String ip = getIpByClient(client); if (uid != null) { log.info("接收到SID:{}发来的消息:{}", uid, data.toJSONString()); log.debug(ip + " ************ 客户端:" + data); } }); socketIOServer.start(); log.info("socket.io初始化服务完成"); } @OnConnect public void onConnect(SocketIOClient client){ log.info(getIpByClient(client)); HandshakeData handshakeData = client.getHandshakeData(); Map> urlParams = handshakeData.getUrlParams(); } @OnEvent(value = "msg") public void OnEvent(SocketIOClient client, AckRequest ackRequest, String data){ log.info("发来消息:" + data); } @OnDisconnect() public void OnEvent(SocketIOClient client){ log.info("{}断开连接",client.getSessionId()); } public void stop() { if (socketIOServer != null) { socketIOServer.stop(); socketIOServer = null; } log.info("socket.io服务已关闭"); } /** * 此方法为获取client连接中的参数,可根据需求更改 * * @param client * @return */ private String getParamsByClient(SocketIOClient client) { // 从请求的连接中拿出参数(这里的sid必须是唯一标识) Map> params = client.getHandshakeData().getUrlParams(); List list = params.get("UID"); if (list != null && list.size() > 0) { return list.get(0); } return null; } /** * 获取连接的客户端ip地址 * * @param client: 客户端 * @return: java.lang.String */ private String getIpByClient(SocketIOClient client) { String sa = client.getRemoteAddress().toString(); return sa.substring(1, sa.indexOf(":")); } }