java版QQ斗地主Socket心跳机制实现思路
小项目开源地址:https://gitee.com/ansatsing/QQLandlords
简要概述:
客户端登录成功后,就持续每隔3秒向服务器端发送心跳包!服务器端每收到一次心跳包就更新lastReveHeatTime的变量值;服务器在启动的时候就开启
一个只针对入座玩家的监听线程,这个线程每隔10秒钟就处理一批超过10秒未发送心跳包的掉线玩家从而以便同步游戏大厅的位置信息!
数据机构:
Player实体类增加属性: private long lastReveHeatTime;//最后一次收到心跳包协议的时间:单位毫秒
客户端增加一个心跳协议消息类:HeartBeatProt;注意:服务器端无需增加!
1 package com.ansatsing.landlords.protocol; 2 3 import com.alibaba.fastjson.JSON; 4 import com.ansatsing.landlords.entity.Player; 5 6 import java.io.Serializable; 7 8 /** 9 * socket心跳协议--主要检测客户端的是否还连接! 10 */ 11 public class HeartBeatProt extends AbstractProtocol implements Serializable { 12 private String msg = "我还活着呢!"; 13 14 public String getMsg() { 15 return msg; 16 } 17 18 public HeartBeatProt(Player player) { 19 super.player = player; 20 } 21 22 @Override 23 public void sendMsg() { 24 super.sendMsg(this.getClass().getName()+ JSON.toJSONString(this)); 25 } 26 }
客户端:
增加一个每隔3秒就发送一个心跳包给服务器端的线程:com.ansatsing.landlords.client.thread
package com.ansatsing.landlords.client.thread; import com.ansatsing.landlords.entity.Player; import com.ansatsing.landlords.protocol.AbstractProtocol; import com.ansatsing.landlords.protocol.HeartBeatProt; import java.util.concurrent.TimeUnit; /** * 心跳线程 */ public class HeartBeatThread implements Runnable { private volatile boolean isStop = false; private Player player; public HeartBeatThread(Player player) { this.player = player; } public void stop(){ this.isStop = true; } public void run() { while(!isStop){ AbstractProtocol heartBeatProt = new HeartBeatProt(player); heartBeatProt.sendMsg(); try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { e.printStackTrace(); } } } }
服务器端
增加一个专门监听超过10秒未发送心跳包的掉线客户端,监听只针对入座的玩家!
1 package com.ansatsing.landlords.server.thread; 2 3 import com.ansatsing.landlords.entity.Player; 4 5 import java.io.IOException; 6 import java.util.Iterator; 7 import java.util.Map; 8 import java.util.concurrent.TimeUnit; 9 10 /** 11 * 监听那些玩家掉线了,掉线了就踢掉:主要针对入座位置的玩家,没有入座的玩家不监听 12 */ 13 public class HeartBeatMonitor implements Runnable { 14 private Map<Integer, Player> playerMap;; 15 public HeartBeatMonitor(Map<Integer, Player> playerMap){ 16 this.playerMap = playerMap; 17 } 18 public void run() { 19 while (true){ 20 try { 21 TimeUnit.SECONDS.sleep(10); 22 } catch (InterruptedException e) { 23 e.printStackTrace(); 24 } 25 Iterator iterator = playerMap.entrySet().iterator(); 26 while(iterator.hasNext()){ 27 Map.Entry<Integer,Player> entry = (Map.Entry<Integer,Player>)iterator.next(); 28 Player player = entry.getValue(); 29 if(System.currentTimeMillis() - player.getLastReveHeatTime() > 10000 ){ 30 if(player.getSocket() != null){ 31 try { 32 player.setUnnormalExited(true); 33 player.getSocket().close(); 34 } catch (IOException e) { 35 e.printStackTrace(); 36 } 37 } 38 } 39 } 40 } 41 } 42 }
如有不对,欢迎指教!谢谢!或者有更好的思路欢迎留言直接我,本人是菜鸟!