当前位置: 首页 > wzjs >正文

自己做pc网站建设今日热点新闻15条

自己做pc网站建设,今日热点新闻15条,youtube上做美食的视频网站,百度网址大全网址导航1.背景: 对于一款网络游戏来说,聊天是基础的交互功能。常见了聊天频道有私聊,世界,公会,队伍,甚至所有服都连接起来的全服聊天。 本文主要目的是,设计一套简单通用的聊天框架。 基本思想&…

1.背景:

对于一款网络游戏来说,聊天是基础的交互功能。常见了聊天频道有私聊,世界,公会,队伍,甚至所有服都连接起来的全服聊天。

本文主要目的是,设计一套简单通用的聊天框架。

基本思想:

使用统一的API处理所有的聊天频道。

并非所有聊天记录都需要存放到数据库,例如世界聊天,由于交互时效问题,重启丢失消息也可以接受。

2.聊天基础

基本流程是:

  1. 当玩家发送聊天的请求消息,先判断指定的频道能否发送,例如私聊的时候我方是否是对方的黑名单;
  2. 验证通过后,将消息保存到内存或者数据库,直接返回发送成功的返回值给客户端;
  3. 服务器收集指定频道的消息接收者列表,异步推送给所有玩家。
  4. 当玩家登录的时候,需要统一收集所有频道的离线消息,一次性推给客户端。

对一些基础的操作作抽象,如下:

/*** 聊天频道处理器*/
public interface ChatChannelHandler {/*** 发送消息之前的检查,例如等级要求,禁言等* @return 错误码*/int checkCanSend(PlayerEnt player, String target, String content);/*** 保存到内存或者数据库* @param message*/void cacheOrSave(ChatMessage message);/*** 角色登录的消息收集* @param player* @return*/List<ChatMessage> collectMessageOnLogin(PlayerEnt player);/*** 收到消息后,进行广播** @param message*/default void broadcast(ChatMessage message) {// 过滤不在线的玩家Collection<String> receivers = receivers(message).stream().filter(p -> SpringContext.getSessionManager().getSessionBy(p) != null).collect(Collectors.toSet());if (CollectionUtils.isEmpty(receivers)) {return;}PushChatNewMessage pushChatNewMessage = new PushChatNewMessage();pushChatNewMessage.setMessages(Collections.singletonList(message));for (String receiver : receivers) {MessageUtil.pushMessage(receiver, pushChatNewMessage);}}/*** 消息接收者列表, 可以不考虑玩家是否在线,底层会自动过滤** @param message* @return*/Collection<String> receivers(ChatMessage message);/*** 频道类型* @return*/byte channelType();}

3.私聊频道

对于私聊,有一个比较有争议的问题是,聊天记录只存一份,还是发送方/接收方独立存一份拷贝这个问题的本质是聊天软件对消息内容的存储方式,一种是扩散读,也就是消息只存一份;另外一种是扩散写,每个接收者独立存储一份副本。

对于游戏的聊天系统,远没有聊天软件那般复杂。

如果聊天记录不允许手动删除,而是由系统过期自动清除。考虑只存一份即可。类似下面的表定义。

这种方式,数据不会冗余,但有一个问题,如果程序使用了缓存,就稍微有点麻烦。当发送方或者接收方独立上线的时候,需要先查询发送方id或者接收方id是当前玩家的所有聊天记录的id,再通过这个id去查询缓存。

当然,如果聊天记录支持手动删除,为了不影响对方的聊天记录,只能双方各存一份拷贝了。 

比较直接的是,玩家身上存一个map,记录该玩家发送的,以及接收的所有消息记录。示例如下:

    /*** 私人聊天记录* key: 对方id* value: 消息列表*/private Map<String, List<ChatMessage>> privateChat = new HashMap<>();public void addNewMessage(String targetId, ChatMessage message) {privateChat.putIfAbsent(targetId, new LinkedList<>());List<ChatMessage> messages = privateChat.get(targetId);if (messages.size() >= 50) {messages.remove(0);}messages.add(message);}

 这种方式也有一个问题,就是如果发送消息的目标玩家是离线状态,为了把新消息发送给接收方,业务需要把离线用户从数据库捞取上来,有造成离线玩家缓存内存过大的风险。针对这种情况 ,可以把聊天记录作为一个单独的表设计,表结构只需要一个玩家id,以及一个保存聊天记录json数据的字段,以此减少程序内存。

本文为了方便,将聊天记录作为玩家表的一个字段,并非推荐方式。

代码如下:

/*** 私人聊天频道*/
public class PrivateChannelHandler implements ChatChannelHandler {@Overridepublic int checkCanSend(PlayerEnt player, String target, String content) {// 对方是否我的好友return 0;}@Overridepublic void cacheOrSave(ChatMessage message) {// 发送方,接收方,各存储一份拷贝PlayerEnt from = GameContext.playerService.getPlayer(message.getSenderId());from.getExtendBox().addNewMessage(message.getReceiverId(), message);GameContext.playerService.savePlayer(from);// 把消息存储到接收者的私聊列表中,如果离线,也要捞起来PlayerEnt target = GameContext.playerService.getPlayer(message.getReceiverId());// 丢到对方线程跑ThreadSafeUtil.addPlayerTask(target, () -> target.getExtendBox().addNewMessage(message.getSenderId(), message));}@Overridepublic List<ChatMessage> collectMessageOnLogin(PlayerEnt player) {return player.getExtendBox().getPrivateChat().values().stream().flatMap(List::stream).collect(Collectors.toList());}@Overridepublic Collection<String> receivers(ChatMessage message) {List<String> receivers = new LinkedList<>();// 发送方+接收方receivers.add(message.getReceiverId());receivers.add(message.getReceiverId());return receivers;}@Overridepublic byte channelType() {return Channels.PERSON;}
}

有一点需要注意的是,在投放接收者消息的时候,需要考虑线程安全问题。

4.世界频道

世界频道,即为单服的全服聊天。可能有些游戏,会定义为所有游戏服节点的全服聊天,这里只是概念的差异。

/*** 世界聊天频道*/
public class WorldChannelHandler implements ChatChannelHandler {// 世界聊天消息缓存// 最大100条消息,30分钟过期private LazyCacheMap<Long, ChatMessage> worldChatCache = new LazyCacheMap<>(100, 30 * TimeUtil.MILLIS_PER_MINUTE);@Overridepublic int checkCanSend(PlayerEnt player, String target, String content) {return 0;}@Overridepublic void cacheOrSave(ChatMessage message) {//世界聊天消息不需要存储到数据库, 只存储在内存中worldChatCache.put(message.getId(), message);}@Overridepublic List<ChatMessage> collectMessageOnLogin(PlayerEnt player) {return worldChatCache.getAllRecords();}@Overridepublic Collection<String> receivers(ChatMessage message) {return GameContext.playerService.getOnlinePlayers().keySet();}@Overridepublic byte channelType() {return Channels.WORLD;}
}

5.业务代码

处理聊天消息发送

/*** 消息发送* @param player 发送者* @param channel* @param content 聊天内容* @param target 发送目标,若为私聊频道,代表接收者id。若为世界频道,该参数为空。*/
public int sendMessage(PlayerEnt player, byte channel, String content, String target) {ChatChannelHandler handler = handlers.get(channel);AssertPlus.isFalse(handler == null);int errCode = handler.checkCanSend(player, target, content);if (errCode > 0) {return errCode;}// 这里要用异步广播ChatMessage message = new ChatMessage();message.setChannel(channel);message.setSenderId(player.getId());message.setReceiverId(target);message.setContent(content);handler.cacheOrSave(message);handler.broadcast(message);return 0;
}

处理登录下发离线消息

/*** 登录的时候,收集所有频道的离线聊天,统一下发* @param player*/
public void notifyNewMessageOnLogin(PlayerEnt player) {PushChatNewMessage push = new PushChatNewMessage();List<ChatMessage> messages = new LinkedList<>();handlers.values().forEach(handler->{messages.addAll(handler.collectMessageOnLogin(player));});push.setMessages(messages);MessageUtil.pushMessage(player, push);
}

http://www.dtcms.com/wzjs/219745.html

相关文章:

  • 南昌做网站后台投票郑州网站优化顾问
  • 政府网站建设方案书中国网评中国网评
  • 做网站开发学什么网络营销方案
  • 郑州市政务公开优化师助理
  • 为什么有点网站打不开登封网站设计
  • 南昌简单做网站东莞互联网公司排名
  • 子目录创建网站sem代运营公司
  • 广告设计与制作包括哪些内容北京网站优化体验
  • wordpress主题视频教程搜索引擎优化叫什么
  • 网站开发培训什么手机如何制作网站
  • 网站建设的7种流程图厦门网络推广培训
  • dw响应式网站模板下载关键词搜索推广
  • 网站开发费用算无形资产吗关键词排名查询工具免费
  • 网站备案现状搜狗搜索网页版
  • 怎么在网上建网站啊百度指数app
  • wordpress媒体库 不显示学seo需要学什么专业
  • 主流科技类的网站都有哪些朋友圈推广平台
  • 网站建设iis竞价推广托管开户
  • 专业网站制作咨询微商引流一般用什么软件
  • 丽水企业网站开发企业全自动推广软件
  • 综述题建设网站需要几个步骤微信推广费用一般多少
  • 北京网络科技公司有哪些成都seo外包
  • 网站建设北京企业seo顾问公司
  • 电子网站建设怎么做企业策划书
  • 如何选择锦州网站建设广东seo网站推广代运营
  • 有了虚拟主机怎么做网站国家提供的免费网课平台
  • 用自己的名字做网站域名简述什么是seo
  • 合肥网站搭建一站式自媒体服务平台
  • 中核华泰建设有限公司网站百度公司总部
  • 建设网站可以做什么本地建站软件有哪些