zoukankan      html  css  js  c++  java
  • 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
     
  • 相关阅读:
    排序算法之冒泡排序
    hadoop程序启动
    开播小记
    3.3面向对象封装案例1摆家具
    3.2面向对象基础语法
    3.1类和对象
    2.12函数进阶
    2.11变量的引用_可变不可变类型_局部变量和全局变量
    2.10第二章综合应用_名片管理系统
    2.8函数基础
  • 原文地址:https://www.cnblogs.com/tushengadbm/p/14150653.html
Copyright © 2011-2022 走看看