在使用socket.io跟前端通信过程中,出现了一系列问题,现做下记录。
一、功能需求
在小程序端,用户可相互邀请,进入房间后进行答题PK。实现方法是,用户点击邀请好友,建立连接,查询当前是否有房间,有房间发送消息给两人,匹配成功,开始pk。没有房间新建房间返回,等待20秒,等待别人匹配。
代码如下,先看配置,在application.yml配置文件中增加如下配置
配置类
package com.cwn.wethink.remy.handler;
import com.corundumstudio.socketio.SocketConfig;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.corundumstudio.socketio.SocketIOServer;
/**
* @description:
* @author: m1575
* @create: 2020-11-11
**/
@Configuration
class SocketIOConfig {
@Value("${socketio.host}")
private String host;
@Value("${socketio.port}")
private Integer port;
@Value("${socketio.bossCount}")
private int bossCount;
@Value("${socketio.workCount}")
private int workCount;
@Value("${socketio.allowCustomRequests}")
private boolean allowCustomRequests;
@Value("${socketio.upgradeTimeout}")
private int upgradeTimeout;
@Value("${socketio.pingTimeout}")
private int pingTimeout;
@Value("${socketio.pingInterval}")
private int pingInterval;
/**
* 以下配置在上面的application.properties中已经注明
* @return
*/
@Bean
public SocketIOServer socketIOServer() {
SocketConfig socketConfig = new SocketConfig();
socketConfig.setTcpNoDelay(true);
socketConfig.setSoLinger(0);
com.corundumstudio.socketio.Configuration config = new com.corundumstudio.socketio.Configuration();
config.setSocketConfig(socketConfig);
config.setHostname(host);
config.setPort(port);
config.setBossThreads(bossCount);
config.setWorkerThreads(workCount);
config.setAllowCustomRequests(allowCustomRequests);
config.setUpgradeTimeout(upgradeTimeout);
config.setPingTimeout(pingTimeout);
config.setPingInterval(pingInterval);
return new SocketIOServer(config);
}
}
后台实现
package com.cwn.wethink.remy.handler;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import com.alibaba.fastjson.JSONObject;
import com.corundumstudio.socketio.*;
import com.cwn.wethink.pojo.entity.Question;
import com.cwn.wethink.remy.entity.PkAgainGame;
import com.cwn.wethink.remy.entity.PkAnswerTime;
import com.cwn.wethink.remy.entity.PkGroup;
import com.cwn.wethink.remy.entity.WxUserInfo;
import com.cwn.wethink.remy.mapper.PkMapper;
import com.cwn.wethink.remy.mapper.WxUserInfoMapper;
import com.cwn.wethink.remy.service.RemyCourseService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
@Slf4j
public class MessageEventHandler {
// 用来存已连接的客户端
private static Map<Long, SocketIOClient> clientMap = new ConcurrentHashMap<>();
@Autowired
private SocketIOServer socketIOServer;
@Autowired
private PkMapper pkMapper;
@Autowired
private WxUserInfoMapper wxUserInfoMapper;
@Autowired
private RemyCourseService remyCourseService;
/**
* Spring IoC容器创建之后,在加载SocketIOServiceImpl Bean之后启动
* @throws Exception
*/
@PostConstruct
private void autoStartup() throws Exception {
start();
}
/**
* Spring IoC容器在销毁SocketIOServiceImpl Bean之前关闭,避免重启项目服务端口占用问题
* @throws Exception
*/
@PreDestroy
private void autoStop() throws Exception {
stop();
}
public void start() {
// 监听客户端连接,同级挑战比拼
socketIOServer.addConnectListener(client -> {
Long uid = Long.valueOf(getParamsByClient(client));
log.info("connect come in,uid:{}",uid);
//0为同级挑战,1为邀请好友pk
int type = 0;
//房间号
int pkId = 0;
//从请求的连接中拿出参数
Map<String, List<String>> params = client.getHandshakeData().getUrlParams();
List<String> list = params.get("type");
if (list != null &&