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
 
原文地址:https://www.cnblogs.com/tushengadbm/p/14150653.html