• Java后端使用socketio,实现小程序答题pk功能


    在使用socket.io跟前端通信过程中,出现了一系列问题,现做下记录。

    一、功能需求是,在小程序端,用户可相互邀请,进入房间后进行答题PK。实现方法是,用户点击邀请好友,建立连接,查询当前是否有房间,有房间发送消息给两人,匹配成功,开始pk。没有房间新建房间返回,等待20秒,等待别人匹配。

           代码如下,先看配置,在application.yml配置文件中增加如下配置

     1 # host在本地测试可以设置为localhost或者本机IP,在Linux服务器跑可换成服务器IP
     2 socketio:
     3   host: 127.0.0.1    #监听的ip
     4   port: 9999        #监听端口
     5  # 设置最大每帧处理数据的长度,防止他人利用大数据来攻击服务器
     6   maxFramePayloadLength: 1048576
     7   # 设置http交互最大内容长度
     8   maxHttpContentLength: 1048576
     9   # socket连接数大小(如只监听一个端口boss线程组为1即可)
    10   bossCount: 1
    11   workCount: 100
    12   allowCustomRequests: true
    13   # 协议升级超时时间(毫秒),默认10秒。HTTP握手升级为ws协议超时时间
    14   upgradeTimeout: 1000000
    15   # Ping消息超时时间(毫秒),默认60秒,这个时间间隔内没有接收到心跳消息就会发送超时事件
    16   pingTimeout: 6000000
    17   # Ping消息间隔(毫秒),默认25秒。客户端向服务器发送一条心跳消息间隔
    18   pingInterval: 25000
    View Code

    配置类

     1 package com.cwn.wethink.remy.handler;
     2 
     3 
     4 import com.corundumstudio.socketio.SocketConfig;
     5 import org.springframework.beans.factory.annotation.Value;
     6 import org.springframework.context.annotation.Bean;
     7 import org.springframework.context.annotation.Configuration;
     8 
     9 import com.corundumstudio.socketio.SocketIOServer;
    10 
    11 /**
    12  * @description:
    13  * @author: m1575
    14  * @create: 2020-11-11
    15  **/
    16 @Configuration
    17 class SocketIOConfig {
    18 
    19     @Value("${socketio.host}")
    20     private String host;
    21 
    22     @Value("${socketio.port}")
    23     private Integer port;
    24 
    25     @Value("${socketio.bossCount}")
    26     private int bossCount;
    27 
    28     @Value("${socketio.workCount}")
    29     private int workCount;
    30 
    31     @Value("${socketio.allowCustomRequests}")
    32     private boolean allowCustomRequests;
    33 
    34     @Value("${socketio.upgradeTimeout}")
    35     private int upgradeTimeout;
    36 
    37     @Value("${socketio.pingTimeout}")
    38     private int pingTimeout;
    39 
    40     @Value("${socketio.pingInterval}")
    41     private int pingInterval;
    42 
    43     /**
    44      * 以下配置在上面的application.properties中已经注明
    45      * @return
    46      */
    47     @Bean
    48     public SocketIOServer socketIOServer() {
    49         SocketConfig socketConfig = new SocketConfig();
    50         socketConfig.setTcpNoDelay(true);
    51         socketConfig.setSoLinger(0);
    52         com.corundumstudio.socketio.Configuration config = new com.corundumstudio.socketio.Configuration();
    53         config.setSocketConfig(socketConfig);
    54         config.setHostname(host);
    55         config.setPort(port);
    56         config.setBossThreads(bossCount);
    57         config.setWorkerThreads(workCount);
    58         config.setAllowCustomRequests(allowCustomRequests);
    59         config.setUpgradeTimeout(upgradeTimeout);
    60         config.setPingTimeout(pingTimeout);
    61         config.setPingInterval(pingInterval);
    62         return new SocketIOServer(config);
    63     }
    64 }
    View Code

    后台实现

      1 package com.cwn.wethink.remy.handler;
      2 
      3 import java.util.*;
      4 import java.util.concurrent.ConcurrentHashMap;
      5 import javax.annotation.PostConstruct;
      6 import javax.annotation.PreDestroy;
      7 import com.alibaba.fastjson.JSONObject;
      8 import com.corundumstudio.socketio.*;
      9 import com.cwn.wethink.pojo.entity.Question;
     10 import com.cwn.wethink.remy.entity.PkAgainGame;
     11 import com.cwn.wethink.remy.entity.PkAnswerTime;
     12 import com.cwn.wethink.remy.entity.PkGroup;
     13 import com.cwn.wethink.remy.entity.WxUserInfo;
     14 import com.cwn.wethink.remy.mapper.PkMapper;
     15 import com.cwn.wethink.remy.mapper.WxUserInfoMapper;
     16 import com.cwn.wethink.remy.service.RemyCourseService;
     17 import lombok.extern.slf4j.Slf4j;
     18 import org.springframework.beans.factory.annotation.Autowired;
     19 import org.springframework.stereotype.Service;
     20 
     21 @Service
     22 @Slf4j
     23 public class MessageEventHandler {
     24 
     25     // 用来存已连接的客户端
     26     private static Map<Long, SocketIOClient> clientMap = new ConcurrentHashMap<>();
     27 
     28     @Autowired
     29     private SocketIOServer socketIOServer;
     30 
     31     @Autowired
     32     private PkMapper pkMapper;
     33 
     34     @Autowired
     35     private WxUserInfoMapper wxUserInfoMapper;
     36 
     37     @Autowired
     38     private RemyCourseService remyCourseService;
     39 
     40     /**
     41      * Spring IoC容器创建之后,在加载SocketIOServiceImpl Bean之后启动
     42      * @throws Exception
     43      */
     44     @PostConstruct
     45     private void autoStartup() throws Exception {
     46         start();
     47     }
     48 
     49     /**
     50      * Spring IoC容器在销毁SocketIOServiceImpl Bean之前关闭,避免重启项目服务端口占用问题
     51      * @throws Exception
     52      */
     53     @PreDestroy
     54     private void autoStop() throws Exception  {
     55         stop();
     56     }
     57 
     58     public void start() {
     59         // 监听客户端连接,同级挑战比拼
     60         socketIOServer.addConnectListener(client -> {
     61             Long uid = Long.valueOf(getParamsByClient(client));
     62             log.info("connect come in,uid:{}",uid);
     63             //0为同级挑战,1为邀请好友pk
     64             int type = 0;
     65             //房间号
     66             int pkId = 0;
     67             //从请求的连接中拿出参数
     68             Map<String, List<String>> params = client.getHandshakeData().getUrlParams();
     69             List<String> list = params.get("type");
     70             if (list != null && list.size() > 0) {
     71                 type = Integer.valueOf(list.get(0));
     72             }
     73             List<String> list1 = params.get("pkId");
     74             if (list1 != null && list1.size() > 0) {
     75                 pkId = Integer.valueOf(list1.get(0));
     76             }
     77             if (uid != null) {
     78                 if (clientMap.containsKey(uid)) {
     79                     log.info(uid + "is reconnect");
     80                     clientMap.remove(uid);
     81                     clientMap.put(uid , client);
     82                 }else{
     83                     clientMap.put(uid, client);
     84                     log.info("clientMap:"+clientMap);
     85                     joinSendMessage(uid , client , type , pkId);
     86                 }
     87             }
     88         });
     89 
     90         // 监听客户端断开连接
     91         socketIOServer.addDisconnectListener(client -> {
     92             Long uid = Long.valueOf(getParamsByClient(client));
     93             log.info("disconnect come in,uid:{}",uid);
     94             if (uid != null) {
     95                 log.info("uid is not null come in,uid:{}",uid);
     96                 clientMap.remove(uid);
     97                 client.disconnect();
     98                 //退出通知对手
     99                 Long usrEntId = 0l;
    100                 PkGroup pkGroup = pkMapper.getPkGroupUserNewRoom(uid);
    101                 if(pkGroup != null){
    102                     log.info("pkGroup is not null come in,uid:{}",uid);
    103                     if(uid == pkGroup.getInviteUsrEntId()){
    104                         usrEntId = pkGroup.getAcceptUsrEntId();
    105                     }else if(uid == pkGroup.getAcceptUsrEntId()){
    106                         usrEntId = pkGroup.getInviteUsrEntId();
    107                     }
    108                 }
    109                 if(usrEntId != null && usrEntId != 0l){
    110                     log.info("usrEntId is not null come in,uid:{}",uid);
    111                     log.info("socketIOClient usrEntId:" + usrEntId);
    112                     JSONObject jsonObject = new JSONObject();
    113                     SocketIOClient socketIOClient = clientMap.get(usrEntId);
    114                     if(socketIOClient != null){
    115                         jsonObject.put("disconnect" , 1);
    116                         socketIOClient.sendEvent("ClientReceive" , jsonObject);
    117                     }
    118                 }
    119                 if(clientMap.get(usrEntId) == null || usrEntId == null){
    120                     if(pkGroup != null){
    121                         PkGroup updatePkGroup = pkMapper.getPkGroupById(pkGroup.getId());
    122                         updatePkGroup.setState(2);
    123                         pkMapper.updatePkGroup(updatePkGroup);
    124                         log.info("disconnect opponent is disconnect,uid:{}",uid);
    125                     }
    126                 }
    127             }
    128             log.info("disconnect is success,uid:{}",uid);
    129         });
    130 
    131         // 处理自定义的事件,与连接监听类似
    132         // 此示例中测试的json收发 所以接收参数为JSONObject 如果是字符类型可以用String.class或者Object.class
    133         socketIOServer.addEventListener("ServerReceive",JSONObject.class, (client, data, ackSender) -> {
    134             JSONObject jsonObject = data;
    135             if(data != null){
    136                 String uid = jsonObject.getString("usrEntId");
    137                 String action = jsonObject.getString("action");
    138                 if("getAI".equals(action)){
    139                     log.info("getAI come in,uid:{}",uid);
    140                     //和人机pk返回
    141                     botSendMessage(uid , client);
    142                 }else if("challenge".equals(action)){
    143                     log.info("challenge come in,uid:{}",uid);
    144                     //pk过程中每做一道题返回消息给两个人
    145                     int pkId = 0;
    146                     if(!"".equals(jsonObject.getString("pkId"))){
    147                         pkId = Integer.valueOf(jsonObject.getString("pkId"));
    148                     }
    149                     if(pkId == 0){
    150                         log.info("challenge pkId is 0");
    151                         return;
    152                     }
    153                     long usrEntId = -1;
    154                     if(!"".equals(jsonObject.getString("usrEntId"))){
    155                         usrEntId = Long.valueOf(jsonObject.getString("usrEntId"));
    156                     }
    157                     if(usrEntId == -1){
    158                         log.info("challenge usrEntId is -1");
    159                         return;
    160                     }
    161                     int answer = 0;
    162                     if(!"".equals(jsonObject.getString("answer"))){
    163                         answer = Integer.valueOf(jsonObject.getString("answer"));
    164                     }
    165                     int time = 0;
    166                     if(!"".equals(jsonObject.getString("time"))){
    167                         time = Integer.valueOf(jsonObject.getString("time"));
    168                     }
    169                     int queResId = 0;
    170                     if(!"".equals(jsonObject.getString("queResId"))){
    171                         queResId = Integer.valueOf(jsonObject.getString("queResId"));
    172                     }
    173                     int orderNum = 0;
    174                     if(!"".equals(jsonObject.getString("orderNum"))){
    175                         orderNum = Integer.valueOf(jsonObject.getString("orderNum"));
    176                     }
    177                     int option = 0;
    178                     if(!"".equals(jsonObject.getString("option"))){
    179                         option = Integer.valueOf(jsonObject.getString("option"));
    180                     }
    181                     PkAnswerTime  pkAnswerNow = new PkAnswerTime();
    182                     pkAnswerNow.setPkGroupId(pkId);
    183                     pkAnswerNow.setUsrEntId(usrEntId);
    184                     pkAnswerNow.setAnswer(answer);
    185                     pkAnswerNow.setTime(time);
    186                     pkAnswerNow.setQueResId(queResId);
    187                     pkAnswerNow.setOrderNum(orderNum);
    188                     pkAnswerNow.setOption(option);
    189                     pkMapper.savePkAnswerTime(pkAnswerNow);
    190                     PkGroup pkGroup = pkMapper.getPkGroupById(pkId);
    191                     if(usrEntId == pkGroup.getInviteUsrEntId()){
    192                         long acceptUsrEntId = pkGroup.getAcceptUsrEntId();
    193                         judgeWinner(acceptUsrEntId , pkAnswerNow ,client);
    194                     }else if(usrEntId == pkGroup.getAcceptUsrEntId()){
    195                         long inviteUsrEntId = pkGroup.getInviteUsrEntId();
    196                         judgeWinner(inviteUsrEntId , pkAnswerNow ,client);
    197                     }
    198                 }else if("again".equals(action)){
    199                     log.info("again come in");
    200                     //再来一局
    201                     int pkId = Integer.valueOf(jsonObject.getString("pkId"));
    202                     log.info("pkId:"+pkId+"uid:"+uid);
    203                     againSendMessage(uid , pkId, client);
    204                 }else if("skill".equals(action)){
    205                     //使用技能
    206                     int pkId = Integer.valueOf(jsonObject.getString("pkId"));
    207                     //技能id
    208                     int infoId = Integer.valueOf(jsonObject.getString("info"));
    209                     skillSendMessage(uid , pkId , infoId);
    210                 }
    211             }
    212         });
    213 
    214         socketIOServer.start();
    215         log.info("socket.io初始化服务完成");
    216     }
    217 
    218     public void stop() {
    219         if (socketIOServer != null) {
    220             socketIOServer.stop();
    221             socketIOServer = null;
    222         }
    223         log.info("socket.io服务已关闭");
    224     }
    225 
    226     /**
    227      * 此方法为获取client连接中的参数,可根据需求更改
    228      * @param client
    229      * @return
    230      */
    231     private String getParamsByClient(SocketIOClient client) {
    232         // 从请求的连接中拿出参数(这里的usrEntId必须是唯一标识)
    233         Map<String, List<String>> params = client.getHandshakeData().getUrlParams();
    234         List<String> list = params.get("usrEntId");
    235         if (list != null && list.size() > 0) {
    236             return list.get(0);
    237         }
    238         return null;
    239     }
    240 
    241     private synchronized void joinSendMessage(long usrEntId , SocketIOClient client , int type , int pkId){
    242         // 给客户端发送一条信息 发送ConnectReceive事件 需要客户端绑定此事件即可接收到消息
    243         JSONObject jsonObject = new JSONObject();
    244         Date date = new Date(new Date().getTime() - 20000);
    245         PkGroup pkGroup = pkMapper.getPkGroupByState(usrEntId , type , date);
    246         if(type != 0 && pkId != 0){
    247             pkGroup = pkMapper.getPkGroupById(pkId);
    248         }
    249         if(type != 0 && pkId == 0){
    250             pkGroup = null;
    251         }
    252         if(pkGroup != null){
    253             pkGroup.setAcceptUsrEntId(usrEntId);
    254             pkGroup.setState(1);
    255             pkMapper.updatePkGroup(pkGroup);
    256             long inviteUsrEntId = pkGroup.getInviteUsrEntId();
    257             WxUserInfo invite = wxUserInfoMapper.queryWxUserInfoByUsrEntId(inviteUsrEntId);
    258             List<Question> questions = remyCourseService.listGetRandomTopic(0);
    259             jsonObject.put("state" , 1);
    260             jsonObject.put("wxUserInfo" , invite);
    261             jsonObject.put("questions" , questions);
    262             jsonObject.put("pkId" , pkGroup.getId());
    263             client.sendEvent("ConnectReceive",jsonObject);
    264             SocketIOClient socketIOClient = clientMap.get(inviteUsrEntId);
    265             WxUserInfo accept = wxUserInfoMapper.queryWxUserInfoByUsrEntId(usrEntId);
    266             JSONObject acceptJson = new JSONObject();
    267             acceptJson.put("state" , 1);
    268             acceptJson.put("questions" , questions);
    269             acceptJson.put("pkId" , pkGroup.getId());
    270             acceptJson.put("wxUserInfo" , accept);
    271             socketIOClient.sendEvent("ConnectReceive" , acceptJson);
    272         }else{
    273             PkGroup savePkGroup = new PkGroup();
    274             savePkGroup.setInviteUsrEntId(usrEntId);
    275             savePkGroup.setState(0);
    276             savePkGroup.setCreateTime(new Date());
    277             savePkGroup.setType(type);
    278             pkMapper.savePkGroup(savePkGroup);
    279             jsonObject.put("state" , 0);
    280             jsonObject.put("pkId" , savePkGroup.getId());
    281             client.sendEvent("ConnectReceive",jsonObject);
    282         }
    283     }
    284 
    285     private synchronized void botSendMessage(String uid , SocketIOClient client){
    286         JSONObject jsonObject = new JSONObject();
    287         PkGroup pkGroup = pkMapper.getPkGroupByUsrEntIdToAI(Long.valueOf(uid));
    288         if(pkGroup != null){
    289             log.info("getAI pkGroup is not null come in,uid:{}",uid);
    290             pkGroup.setAcceptUsrEntId(0l);
    291             pkGroup.setState(1);
    292             pkMapper.updatePkGroup(pkGroup);
    293             List<Question> questions = remyCourseService.listGetRandomTopic(0);
    294             jsonObject.put("state" , 1);
    295             jsonObject.put("questions" , questions);
    296             jsonObject.put("pkId" , pkGroup.getId());
    297             client.sendEvent("AIReceive",jsonObject);
    298         }
    299     }
    300 
    301     private synchronized void judgeWinner(long anotherEntId , PkAnswerTime  pkAnswerNow, SocketIOClient client){
    302         log.info("judgeWinner come in,anotherEntId:{}",anotherEntId);
    303         int pkId = pkAnswerNow.getPkGroupId();
    304         int orderNum = pkAnswerNow.getOrderNum();
    305         int answer = pkAnswerNow.getAnswer();
    306         int time = pkAnswerNow.getTime();
    307         long usrEntId = pkAnswerNow.getUsrEntId();
    308         int option = pkAnswerNow.getOption();
    309         JSONObject json = new JSONObject();
    310         PkAnswerTime pkAnswerTime = pkMapper.getPkAnswerTimeByParam(anotherEntId , pkId , orderNum);
    311         if(pkAnswerTime != null){
    312             log.info("judgeWinner pkAnswerTime is not null come in,pkAnswerTime:{}",pkAnswerTime);
    313             PkGroup pkGroup = pkMapper.getPkGroupById(pkId);
    314             if(orderNum == 5){
    315                 pkGroup.setState(2);
    316                 pkMapper.updatePkGroup(pkGroup);
    317             }
    318             long winUsrEntId = -1;
    319             if(pkAnswerTime.getAnswer() == 1 && answer == 1){
    320                 if(time > pkAnswerTime.getTime()){
    321                     winUsrEntId = anotherEntId;
    322                 }else if(time < pkAnswerTime.getTime()){
    323                     winUsrEntId = usrEntId;
    324                 }else{
    325                     winUsrEntId = -1;
    326                 }
    327             }else if(pkAnswerTime.getAnswer() == 1){
    328                 winUsrEntId = anotherEntId;
    329             }else if(answer == 1){
    330                 winUsrEntId = usrEntId;
    331             }else{
    332                 winUsrEntId = -1;
    333             }
    334             json.put("winUsrEntId" , winUsrEntId);
    335             json.put("pkId" , pkId);
    336             json.put("usrEntId" , anotherEntId);
    337             json.put("answer" , pkAnswerTime.getAnswer());
    338             json.put("time" , pkAnswerTime.getTime());
    339             json.put("option" , pkAnswerTime.getOption());
    340             client.sendEvent("challengeReceive",json);
    341             if(anotherEntId != 0){
    342                 SocketIOClient socketIOClient = clientMap.get(anotherEntId);
    343                 JSONObject acceptJson = new JSONObject();
    344                 acceptJson.put("pkId" , pkId);
    345                 acceptJson.put("usrEntId" , usrEntId);
    346                 acceptJson.put("answer", answer);
    347                 acceptJson.put("time", time);
    348                 acceptJson.put("option",option);
    349                 acceptJson.put("winUsrEntId",winUsrEntId);
    350                 socketIOClient.sendEvent("challengeReceive" , acceptJson);
    351             }
    352             if(pkGroup.getInviteUsrEntId() == winUsrEntId){
    353                 if(pkGroup.getInviteNum() != null){
    354                     pkGroup.setInviteNum(pkGroup.getInviteNum() + 1);
    355                 }else{
    356                     pkGroup.setInviteNum(1);
    357                 }
    358             }else if(pkGroup.getAcceptUsrEntId() == winUsrEntId){
    359                 if(pkGroup.getAcceptNum() != null){
    360                     pkGroup.setAcceptNum(pkGroup.getAcceptNum() + 1);
    361                 }else{
    362                     pkGroup.setAcceptNum(1);
    363                 }
    364             }
    365             pkMapper.updatePkNum(pkGroup);
    366         }
    367     }
    368 
    369     private synchronized void againSendMessage(String uid , int pkId , SocketIOClient client){
    370         JSONObject json = new JSONObject();
    371         long usrEntId = Long.valueOf(uid);
    372         PkGroup pkGroup = pkMapper.getPkGroupById(pkId);
    373         log.info("againSendMessage pkGroup:"+pkGroup);
    374         long opponentId = -1;
    375         if(pkGroup.getAcceptUsrEntId() != null){
    376             if(usrEntId == pkGroup.getAcceptUsrEntId()){
    377                 opponentId = pkGroup.getInviteUsrEntId();
    378             }else{
    379                 opponentId = pkGroup.getAcceptUsrEntId();
    380             }
    381         }
    382         PkAgainGame pkAgainGame = pkMapper.getPkAgainGame(opponentId , pkId);
    383         log.info("againSendMessage pkAgainGame:"+pkAgainGame);
    384         if(pkAgainGame == null){
    385             PkAgainGame againGame = new PkAgainGame();
    386             againGame.setCreateTime(new Date());
    387             againGame.setUsrEntId(usrEntId);
    388             againGame.setPkGroupId(pkId);
    389             pkMapper.savePkAgainGame(againGame);
    390             json.put("usrEntId" , usrEntId);
    391             json.put("state" , 0);
    392             SocketIOClient socketIOClient = clientMap.get(opponentId);
    393             log.info("againSendMessage socketIOClient:"+socketIOClient);
    394             socketIOClient.sendEvent("AgainReceive" , json);
    395         }else{
    396             pkAgainGame.setOpponentUsrEntId(usrEntId);
    397             pkMapper.updatePkAgainGame(pkAgainGame);
    398             //创建房间
    399             PkGroup savePkGroup = new PkGroup();
    400             savePkGroup.setAcceptUsrEntId(usrEntId);
    401             savePkGroup.setInviteUsrEntId(opponentId);
    402             savePkGroup.setState(1);
    403             savePkGroup.setCreateTime(new Date());
    404             savePkGroup.setType(pkGroup.getType());
    405             pkMapper.savePkGroup(savePkGroup);
    406             List<Question> questions = remyCourseService.listGetRandomTopic(0);
    407             log.info("againSendMessage questions:"+questions);
    408             json.put("state" , 1);
    409             json.put("questions" , questions);
    410             json.put("pkId" , savePkGroup.getId());
    411             if(opponentId == 0){
    412                 json.put("wxUserInfo" , "");
    413             }else{
    414                 WxUserInfo invite = wxUserInfoMapper.queryWxUserInfoByUsrEntId(opponentId);
    415                 json.put("wxUserInfo" , invite);
    416             }
    417             client.sendEvent("AgainReceive",json);
    418             if(opponentId != 0 && opponentId != -1){
    419                 SocketIOClient socketIOClient = clientMap.get(opponentId);
    420                 JSONObject acceptJson = new JSONObject();
    421                 acceptJson.put("state" , 1);
    422                 acceptJson.put("questions" , questions);
    423                 acceptJson.put("pkId" , savePkGroup.getId());
    424                 WxUserInfo accept = wxUserInfoMapper.queryWxUserInfoByUsrEntId(usrEntId);
    425                 acceptJson.put("wxUserInfo" , accept);
    426                 log.info("againSendMessage socketIOClient:"+socketIOClient);
    427                 socketIOClient.sendEvent("AgainReceive" , acceptJson);
    428             }
    429         }
    430     }
    431 
    432     private void skillSendMessage(String uid , int pkId , int infoId){
    433         JSONObject json = new JSONObject();
    434         long usrEntId = Long.valueOf(uid);
    435         PkGroup pkGroup = pkMapper.getPkGroupById(pkId);
    436         log.info("skillSendMessage pkGroup:"+pkGroup);
    437         long opponentId = -1;
    438         if(usrEntId == pkGroup.getAcceptUsrEntId()){
    439             opponentId = pkGroup.getInviteUsrEntId();
    440         }else{
    441             opponentId = pkGroup.getAcceptUsrEntId();
    442         }
    443         json.put("usrEntId" , usrEntId);
    444         json.put("skill" , 1);
    445         json.put("info" , infoId);
    446         SocketIOClient socketIOClient = clientMap.get(opponentId);
    447         log.info("skillSendMessage socketIOClient:"+socketIOClient);
    448         socketIOClient.sendEvent("SkillReceive" , json);
    449     }
    450 }
    View Code

      二、遇到的一些问题

        1、最初在发送消息给两人时,有个人能收到消息,有个人收不到

    刚开始clientMap是这样声明的:

    private static Map<String, SocketIOClient> clientMap = new ConcurrentHashMap<>();

    但我在查询用户SocketIOClient时使用的是long类型,所以一直没查到用户的SocketIOClient,也就发送消息发不过去。

    后面改为
    private static Map<Long, SocketIOClient> clientMap = new ConcurrentHashMap<>();

    这样声明还是获取不到,继而检查代码,开始返回给两个人的信息对象JSONObject,使用的同一个对象,虽然重新set了值,但还是返回了相同的对象。
     1 JSONObject jsonObject = new JSONObject();
     2 jsonObject.put("state" , 1);
     3 jsonObject.put("wxUserInfo" , invite);
     4 jsonObject.put("questions" , questions);
     5 jsonObject.put("pkId" , pkGroup.getId());
     6 client.sendEvent("ConnectReceive",jsonObject);
     7 SocketIOClient socketIOClient = clientMap.get(inviteUsrEntId);
     8 WxUserInfo accept = wxUserInfoMapper.queryWxUserInfoByUsrEntId(usrEntId);
     9 jsonObject.put("state" , 1);
    10 jsonObject.put("questions" , questions);
    11 jsonObject.put("pkId" , pkGroup.getId());
    12 jsonObject.put("wxUserInfo" , accept);
    13 socketIOClient.sendEvent("ConnectReceive" , jsonObject);
    View Code

    后改为重新new一个JSONObject对象,问题解决。

        2、本地测试没问题,上了测试环境出现问题。连接时间超过1分钟,会自动断开连接。

    后经查是服务器使用了nginx,nginx默认连接60s会断开连接。

    需更改nginx配置,如下:

     1 location /socket.io {
     2                 proxy_pass http://172.17.0.2:9999;
     3                 proxy_set_header Host $host;
     4                 proxy_next_upstream off;
     5                 proxy_buffering off;
     6                 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
     7 
     8                 proxy_http_version 1.1;
     9                 proxy_set_header Upgrade $http_upgrade;
    10                 proxy_set_header Connection "upgrade";
    11                 proxy_read_timeout 3600s;
    12         }
    View Code
    proxy_read_timeout默认为60s,若需要长时间连接,改大点。
       三、前端代码示例
     1 <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.3.0/socket.io.js"></script>
     2     <script type="text/javascript">
     3         const connectEvent = "ConnectReceive";
     4         const aiEvent = "AIReceive";
     5         const challengeEvent = "challengeReceive";
     6         const sendEvent = "ServerReceive";
     7         const againEvent = "AgainReceive";
     8         const clientEvent = "ClientReceive";
     9         const skillEvent = "SkillReceive";
    10         var socket;
    11         function socketClick() {
    12             //连接服务器,返回房间、题目信息
    13             socket = io.connect('http://127.0.0.1:9999', {
    14                 'force new connection': true,
    15                 'query': 'usrEntId=' + 41 + '&type=' + 1
    16             })
    17 
    18             socket.on(connectEvent, function (data) {
    19                 //data:{pkId: 31,state: 0} 房间号、状态为0表示创建了个房间,为1表示有房间并已加入
    20                 //data:{pkId: 31,questions:[{},{}...],state: 1,wxUserInfo:{openId:,unionId:,nickName:,headImg:,empiricalValue:,usrEntId:,createTime:,medal:}}
    21                 console.log(data)
    22             })
    23 
    24             socket.on(clientEvent, function (data) {
    25                 //data:{disconnect: 1} 对手退出了房间
    26                 console.log(data)
    27             })
    28 
    29             socket.on(skillEvent, function (data) {
    30                 //data:{usrEntId:42 , skill: 1 , info:1} 对手id、使用了技能,技能id
    31                 console.log(data)
    32             })
    33 
    34             socket.on(aiEvent, function (data) {
    35                 //data:{pkId: 31,questions:[{},{}...],state: 1} 房间号、题目集合、状态
    36                 console.log(data)
    37             })
    38 
    39             //每道题答完接收消息
    40             socket.on(challengeEvent, function (data) {
    41                 //返回 data:{pkId: 31,winUsrEntId: 41,usrEntId:42,answer:1,time:3} 房间号、赢家id、对手id、答案1对0错、时间
    42                 console.log('ServerReceive成功')
    43             })
    44 
    45             socket.on(againEvent, function (data) {
    46                 //data:{state: 0,usrEntId: 41} state为0邀请信息、邀请再来一局玩家id
    47                 //data:{state: 1,wxUserInfo: {},questions:[{},{}...],pkId} state为1再来一局成功、对手信息、题目、房间号
    48                 console.log(data)
    49             })
    50 
    51             socket.on(clientEvent, function (data) {
    52                 //data:{disconnect: 1} 对手退出了房间
    53                 console.log(data)
    54             })
    55 
    56             //发送和人机pk消息到服务器
    57             send({
    58                 action: 'getAI',
    59                 usrEntId: 41
    60             })
    61 
    62             //每道题答完发送消息到服务器
    63             send({
    64                 action: 'challenge',
    65                 usrEntId: 41,
    66                 answer: 1,
    67                 time: 6,
    68                 pkId: 1,
    69                 orderNum: 1,
    70                 queResId: 1,
    71                 option: 3
    72             })
    73             //再来一局
    74             send({
    75                 action: 'again',
    76                 usrEntId: 41,
    77                 pkId:1
    78             })
    79 
    80             //发送技能
    81             send({
    82                 action: 'skill',
    83                 usrEntId: 41,
    84                 pkId:1
    85             })
    86 
    87         }
    88         function send(data){
    89             socket.emit(sendEvent,data);
    90         }
    91         
    92         function quitClick() {
    93             var data={usrEntId:41};
    94             socket.disconnect();
    95         }
    96     </script>
    View Code
     
  • 相关阅读:
    The formatter threw an exception while trying to deserialize the message in WCF
    通过Web Deploy方式部署WCF
    The Managed Metadata Service or Connection is currently not available
    How to create Managed Metadata Column
    冒泡算法
    asp.net core 实战项目(一)——ef core的使用
    Vue学习笔记入门篇——安装及常用指令介绍
    Vue学习笔记入门篇——数据及DOM
    Vue学习笔记目录
    Chart.js在Laravel项目中的应用
  • 原文地址:https://www.cnblogs.com/tushengadbm/p/14150653.html
Copyright © 2020-2023  润新知