简介
netty-socketio是一个开源的Socket.io服务器端的一个java的实现,它基于Netty框架。socket.io是一个跨浏览器使用websocket为实时实时应用提供服务。
**github:**github.com/mrniko/nett…
maven
<dependency>
<groupId>com.corundumstudio.socketio</groupId>
<artifactId>netty-socketio</artifactId>
<version>2.0.6</version>
</dependency>
@Component
public class MessagePushConfig implements InitializingBean {
private static final Logger logger = LoggerFactory.getLogger(MessagePushConfig.class);
@Resource
private EventListenner eventListenner;
@Value("${socketio.port}")
private int port;
@Autowired
private SocketIOServer socketIOServer;
@Override
public void afterPropertiesSet() throws Exception {
socketIOServer.start();
logger.info("启动正常");
}
@Bean
public SocketIOServer socketIOServer() {
Configuration config = new Configuration();
config.setPort(port);
SocketConfig socketConfig = new SocketConfig();
socketConfig.setReuseAddress(true);
socketConfig.setTcpNoDelay(true);
socketConfig.setSoLinger(0);
config.setSocketConfig(socketConfig);
config.setExceptionListener(new ExceptionListenerAdapter(){
@Override
public boolean exceptionCaught(ChannelHandlerContext ctx, Throwable e) throws Exception {
logger.debug("错误:"+e.getMessage());
ctx.close();
return true;
}
});
SocketIOServer server = new SocketIOServer(config);
server.addListeners(eventListenner);
return server;
}
}
@Component
public class EventListenner {
private static final Logger logger = LoggerFactory.getLogger(EventListenner.class);
@Resource
private ClientCache clientCache;
@Autowired
private RedisTemplate<Object, Object> redisTemplate;
/**
* 客户端连接
*
* @param client
*/
@OnConnect
public void onConnect(SocketIOClient client) {
String userId = client.getHandshakeData().getSingleUrlParam("userId");
if(!StringUtils.isEmpty(userId)) {
UUID sessionId = client.getSessionId();
clientCache.saveClient(userId, sessionId, client);
logger.info("建立连接:" + userId);
}
}
/**
* 客户端断开
*
* @param client
*/
@OnDisconnect
public void onDisconnect(SocketIOClient client) {
String userId = client.getHandshakeData().getSingleUrlParam("userId");
clientCache.deleteSessionClient(userId, client.getSessionId());
client.disconnect();
logger.info("关闭连接:" + userId);
}
/**
* 监听客户端事件chat
*
* @param client 客户端信息
* @param request 请求信息
* @param data 客户端发送数据
*/
@OnEvent("chat")
public void onEevent(SocketIOClient client, AckRequest request, ChatMessage message) {
String content = JSON.toJSONString(message);
redisTemplate.convertAndSend("chat", content);
}
/**
* 监听客户端事件room
*
* @param client 客户端信息
* @param request 请求信息
* @param data 客户端发送数据
*/
@OnEvent("room")
public void room(SocketIOClient client, AckRequest request, ChatMessage message) {
String content = JSON.toJSONString(message);
redisTemplate.convertAndSend("room", content);
}
}
@Component
public class ClientCache {
/**
* 本地缓存
*/
private static Map<String, HashMap<UUID, SocketIOClient>> concurrentHashMap = new ConcurrentHashMap<>();
/**
* 存入本地缓存
*
* @param userId 用户ID
* @param sessionId 页面sessionID
* @param socketIOClient 页面对应的通道连接信息
*/
public void saveClient(String userId, UUID sessionId, SocketIOClient socketIOClient) {
HashMap<UUID, SocketIOClient> sessionIdClientCache = concurrentHashMap.get(userId);
if (sessionIdClientCache == null) {
sessionIdClientCache = new HashMap<>();
}
sessionIdClientCache.put(sessionId, socketIOClient);
concurrentHashMap.put(userId, sessionIdClientCache);
}
/**
* 根据用户ID获取所有通道信息
*
* @param userId
* @return
*/
public HashMap<UUID, SocketIOClient> getUserClient(String userId) {
return concurrentHashMap.get(userId);
}
/**
* 根据用户ID及页面sessionID删除页面链接信息
*
* @param userId
* @param sessionId
*/
public void deleteSessionClient(String userId, UUID sessionId) {
concurrentHashMap.get(userId).remove(sessionId);
if(concurrentHashMap.get(userId).isEmpty()) {
concurrentHashMap.remove(userId);
}
}
/**
* 获取所有用户数量
*
* @return
*/
public long getUserNumber() {
return concurrentHashMap.size();
}
}
@Component
public class RedisSub implements MessageListener {
@Resource
private ClientCache clientCache;
@Autowired
private RedisTemplate<Object, Object> redisTemplate;
@Override
public void onMessage(Message message, byte[] pattern) {
String msgString = (String) redisTemplate.getValueSerializer().deserialize(message.getBody());
socketIOClient.sendEvent("chat", msgString);
}
}
npm install socket.io-client@2.2.0
import io from 'socket.io-client'
socket = io.connect(window.platform.socketioUrl + '?userId=' + localStorage.getItem('userId'))
//监听服务器连接事件
socket.on('connect', () => {
console.log('connect')
})
//监听服务器关闭服务事件
socket.on('disconnect', () => {
console.log('disconnect')
})
//连接失败
socket.on('connect_error', err => {
console.log('connect_error:' + err.message)
})
//监听服务器端发送消息事件
socket.on('chat', data => {
})
//发送消息事件
socket.emit('room', event)