[WebSocket]使用WebSocket实现实时多人答题对战游戏
2020-12-16 23:04
标签:知识点 用户创建 连接数 apache 优化 return 协议 sessionid 帮助 前两章教程,我们使用WebSocket的基础特性打造了一个小小聊天室,并在第二章对其进行了集群化改造。 系列教程回顾: 手把手搭建WebSocket多人在线聊天室(SpringBoot+WebSocket) [WebSocket]第二章:WebSocket集群分布式改造——实现多人在线聊天室 在本文中,我将介绍如何使用WebSocket向实时多人答题对战游戏提供服务端,并详细介绍通接口的设计。 这是我在最近作业竞赛中设计的小项目,和小伙伴们一起设计了整个游戏流程和后端代码,前端页面暂时就不放开给大家了,大家可以参考前两章教程自己动手写一下前端页面。 本文内容摘要: 本文源码:(妈妈再也不用担心我无法复现文章代码啦) https://github.com/qqxx6661/websocket-game-demo 参考: https://blog.csdn.net/honey199396/article/details/54603860 优点:协议较成熟,应用广泛、基于TCP/IP,拥有TCP优点、研发成本很低,开发快速、开源软件较多,nginx,apache,tomact等 优点:可靠性 、全双工协议、开源支持多、应用较广泛、面向连接、研发成本低、报文内容不限制(IP层自动分包,重传,不大于1452bytes) 优点:协议较成熟、基于TCP/IP,拥有TCP优点、数据报文较小,包头非常小、面向连接,有状态协议、开源较多,开发较快 优点:操作系统:并发高,内存消耗较低、传输:效率高,网络延迟低、传输模型简单,研发成本低 我们采用websocket作为我们的通信方案,主要是因为我们希望对战双方能够实时显示对方的得分。 本小节详细介绍了我们在线问答对战游戏中,具体的websocket通讯方式定义。 接下来详细介绍这三种WebSocket接口 打开界面,进入游戏: 我们使用了HashMap存储用户状态, 用户状态分为空闲和游戏中: WebSocket接口设计如下: WebSocket接口代码如下: 在大厅中选择玩家,随后会进入对战: 我们使用了HashMap存储了正在对战的用户,给双方配对。 WebSocket接口设计如下: WebSocket接口代码如下: 对战过程中的演示图:左边显示我方分数,右边显示对方分数 WebSocket接口设计如下: WebSocket接口代码如下: 这个只是个两天赶出来的Demo,当然里成品还有非常大的差距。这里有几个需要继续解决的事情: 我们可以使用convertAndSendToUser()方法,按照名字就可以判断出来,convertAndSendToUser()方法能够让我们给特定用户发送消息。 就会被spring websocket利用UserDestinationMessageHandler进行转化成”/topic/greetings-usererbgz2rq”,”usererbgz2rq”中,user是关键字,erbgz2rq是sessionid,这样子就把用户和订阅路径唯一的匹配起来了. 点对点通讯: https://blog.csdn.net/yingxiake/article/details/51224569 我们在本文中实现了在线多人对战游戏的服务端WebSocket接口设计,进一步巩固了对WebSocket的基础和应用范围的理解。 本文工程源代码: https://github.com/qqxx6661/websocket-game-demo 我目前是一名后端开发工程师。主要关注后端开发,数据安全,爬虫,边缘计算等方向。 微信:yangzd1102(请注明来意) Github:@qqxx6661 个人博客: 如果文章对你有帮助,不妨收藏起来并转发给您的朋友们~ [WebSocket]使用WebSocket实现实时多人答题对战游戏 标签:知识点 用户创建 连接数 apache 优化 return 协议 sessionid 帮助 原文地址:https://blog.51cto.com/15047490/2560755前言
正文
WebSocket实现在线多人游戏——对战答题
在线游戏常用的通讯方案
HTTP
缺点:无状态无连接、只有PULL模式,不支持PUSH、数据报文较大
特性:基于TCP/IP应用层协议、无状态,无连接、支持C/S模式、适用于文本传输TCP
缺点:操作系统:较耗内存,支持连接数有限、设计:协议较复杂,自定义应用层协议、网络:网络差情况下延迟较高、传输:效率低于UDP协议
特性:面向连接、可靠性、全双工协议、基于IP层、OSI参考模型位于传输层、适用于二进制传输WebScoket
缺点:
特性:有状态,面向连接、数据报头较小、适用于WEB3.0,以及其他即时联网通讯UDP
缺点:协议不可靠、单向协议、开源支持少、报文内容有限,不能大于1464bytes、设计:协议设计较复杂、网络:网络差,而且丢数据报文
特性:无连接,不可靠,基于IP协议层,OSI参考模型位于传输层,最大努力交付,适用于二进制传输总结
WebSocket实现双人在线游戏实时通信
本问答游戏规则如下:
所以我们需要设计三个WebSocket协议:
用户创建昵称,进入玩家大厅
private Map
public enum StatusEnum {
IDLE,
IN_GAME
}
@MessageMapping("/game.add_user")
@SendTo("/topic/game")
public MessageReply addUser(@Payload ChatMessage chatMessage, SimpMessageHeaderAccessor headerAccessor) throws JsonProcessingException {
MessageReply message = new MessageReply();
String sender = chatMessage.getSender();
ChatMessage result = new ChatMessage();
result.setType(MessageTypeEnum.ADD_USER);
result.setReceiver(Collections.singletonList(sender));
if (userToStatus.containsKey(sender)) {
message.setCode(201);
message.setStatus("该用户名已存在");
message.setChatMessage(result);
log.warn("addUser[" + sender + "]: " + message.toString());
} else {
result.setContent(mapper.writeValueAsString(userToStatus.keySet().stream().filter(k -> userToStatus.get(k).equals(StatusEnum.IDLE)).toArray()));
message.setCode(200);
message.setStatus("成功");
message.setChatMessage(result);
userToStatus.put(sender, StatusEnum.IDLE);
headerAccessor.getSessionAttributes().put("username",sender);
log.warn("addUser[" + sender + "]: " + message.toString());
}
return message;
}
用户选择对手,双方进入游戏
private Map
@MessageMapping("/game.choose_user")
@SendTo("/topic/game")
public MessageReply chooseUser(@Payload ChatMessage chatMessage) throws JsonProcessingException {
MessageReply message = new MessageReply();
String receiver = chatMessage.getContent();
String sender = chatMessage.getSender();
ChatMessage result = new ChatMessage();
result.setType(MessageTypeEnum.CHOOSE_USER);
if (userToStatus.containsKey(receiver) && userToStatus.get(receiver).equals(StatusEnum.IDLE)) {
List
对战过程实时显示双方分数
@MessageMapping("/game.do_exam")
@SendTo("/topic/game")
public MessageReply doExam(@Payload ChatMessage chatMessage) throws JsonProcessingException {
MessageReply message = new MessageReply();
String sender = chatMessage.getSender();
String receiver = userToPlay.get(sender);
ChatMessage result = new ChatMessage();
result.setType(MessageTypeEnum.DO_EXAM);
log.warn("userToStatus:" + mapper.writeValueAsString(userToStatus));
if (userToStatus.containsKey(receiver) && userToStatus.get(receiver).equals(StatusEnum.IN_GAME)) {
result.setContent(chatMessage.getContent());
result.setSender(sender);
result.setReceiver(Collections.singletonList(receiver));
message.setCode(200);
message.setStatus("成功");
message.setChatMessage(result);
log.warn("doExam[" + receiver + "]: " + message.toString());
}else{
result.setReceiver(Collections.singletonList(sender));
message.setCode(203);
message.setStatus("该用户不存在或已退出游戏");
message.setChatMessage(result);
log.warn("doExam[" + sender + "]: " + message.toString());
}
return message;
}
进一步
spring webscoket能识别带”/user”的订阅路径并做出处理,例如,如果浏览器客户端,订阅了’/user/topic/greetings’这条路径,stompClient.subscribe(‘/user/topic/greetings‘, function(data) {
//...
});
参考文献
总结
关注我
原创博客主要内容
个人公众号:后端技术漫谈
个人公众号:后端技术漫谈
文章标题:[WebSocket]使用WebSocket实现实时多人答题对战游戏
文章链接:http://soscw.com/essay/36783.html