热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

(整理)用Elixir做一个多人扑克游戏4

为什么80%的码农都做不了架构师?sockets和channels是Phoenix中用来实现实时效果的两大工具。Socketssocket是用来连接客户端与服务

为什么80%的码农都做不了架构师?>>>   hot3.png

sockets 和 channels 是Phoenix中用来实现实时效果的两大工具。

Sockets

socket是用来连接客户端与服务器的,它使用endpoint来声明:

defmodule GenPoker.Endpoint douse Phoenix.Endpoint, otp_app: :gen_pokersocket "/socket", GenPoker.PlayerSocket
end

Channels

客户端只有加入了channel之后才能发送消息。

defmodule GenPoker.PlayerSocket douse Phoenix.Socketchannel "tables:*", GenPoker.TableChannel
end

创建socket

defmodule GenPoker.PlayerSocket douse Phoenix.Sockettransport :websocket, Phoenix.Transports.WebSocketdef connect(%{"playerId" => player_id}, socket) do{:ok, assign(socket, :player_id, player_id)}enddef id(socket) do "players_socket:#{socket.assigns.player_id}"end
end

注册进程

defmodule Poker.Table douse GenServerdef start_link(table_name, sup, storage, num_seats) doGenServer.start_link(__MODULE__, [table_name, sup, storage, num_seats], name: via_tuple(table_name))enddefp via_tuple(table) do {:via, :gproc, {:n, :l, {:table, table}}}enddef whereis(table) do:gproc.whereis_name({:n, :l, {:table, table}})end
end

我们使用了gproc库来注册进程,这样就可以使用一个term而不仅仅是atom作为名字。让我们来定义Channel:

module GenPoker.TableChannel douse GenPoker.Web, :channelalias Poker.Tabledef join("tables:" <> table, _payload, socket) do{:ok, assign(socket, :table, table)}enddef handle_in(command, payload, socket) when command in ~w(sit leave buy_in cash_out deal) dotable &#61; Table.whereis(socket.assigns.table)arguments &#61; [table, socket.assigns.player_id] &#43;&#43; payloadresult &#61; apply(Table, String.to_atom(command), arguments)if result &#61;&#61; :ok dobroadcast! socket, "update", Table.get_state(table)end{:reply, result, socket}end
end

对于客户端的join请求&#xff0c;我们有不同的回复。在Javascript中可以这样写&#xff1a;

channel.push("message", arguments).receive("ok", (msg) &#61;> console.log("Got OK!")).receive("error", (msg) &#61;> console.log("Oops!"))

发送初始的state

def join("tables:" <> table, _payload, socket) dostate &#61; table |> Table.whereis |> Table.get_statepush socket, "update", state{:ok, assign(socket, :table, table)}
end

使用handle_info

def join("tables:" <> table, _payload, socket) dosend self, :after_join{:ok, assign(socket, :table, table)}
enddef handle_info(:after_join, socket) dostate &#61; socket.assigns.table |> Table.whereis |> Table.get_statepush socket, "update", state{:noreply, socket}
enddef handle_info(_, socket) do{:noreply, socket}
end

拦截消息

def handle_out("update", state, socket) dopush socket, "update", hide_other_hands(state, socket){:noreply, socket}
enddefp hide_other_hands(state, socket) doplayer_id &#61; socket.assigns.player_idhide_hand_if_current_player &#61; fn%{id: ^player_id} &#61; player -> playerplayer -> Map.delete(player, :hand)endupdate_in(state.players, fn players ->Enum.map(players, hide_hand_if_current_player)end)
end

完整代码


转:https://my.oschina.net/ljzn/blog/754811



推荐阅读
  • WebSocket与Socket.io的理解
    WebSocketprotocol是HTML5一种新的协议。它的最大特点就是,服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息,是真正的双向平等对话,属于服务器推送 ... [详细]
  • 利用Visual Basic开发SAP接口程序初探的方法与原理
    本文介绍了利用Visual Basic开发SAP接口程序的方法与原理,以及SAP R/3系统的特点和二次开发平台ABAP的使用。通过程序接口自动读取SAP R/3的数据表或视图,在外部进行处理和利用水晶报表等工具生成符合中国人习惯的报表样式。具体介绍了RFC调用的原理和模型,并强调本文主要不讨论SAP R/3函数的开发,而是针对使用SAP的公司的非ABAP开发人员提供了初步的接口程序开发指导。 ... [详细]
  • 深入理解Kafka服务端请求队列中请求的处理
    本文深入分析了Kafka服务端请求队列中请求的处理过程,详细介绍了请求的封装和放入请求队列的过程,以及处理请求的线程池的创建和容量设置。通过场景分析、图示说明和源码分析,帮助读者更好地理解Kafka服务端的工作原理。 ... [详细]
  • Ihaveaworkfolderdirectory.我有一个工作文件夹目录。holderDir.glob(*)>holder[ProjectOne, ... [详细]
  • 电话号码的字母组合解题思路和代码示例
    本文介绍了力扣题目《电话号码的字母组合》的解题思路和代码示例。通过使用哈希表和递归求解的方法,可以将给定的电话号码转换为对应的字母组合。详细的解题思路和代码示例可以帮助读者更好地理解和实现该题目。 ... [详细]
  • 如何使用Java获取服务器硬件信息和磁盘负载率
    本文介绍了使用Java编程语言获取服务器硬件信息和磁盘负载率的方法。首先在远程服务器上搭建一个支持服务端语言的HTTP服务,并获取服务器的磁盘信息,并将结果输出。然后在本地使用JS编写一个AJAX脚本,远程请求服务端的程序,得到结果并展示给用户。其中还介绍了如何提取硬盘序列号的方法。 ... [详细]
  • 本文介绍了RPC框架Thrift的安装环境变量配置与第一个实例,讲解了RPC的概念以及如何解决跨语言、c++客户端、web服务端、远程调用等需求。Thrift开发方便上手快,性能和稳定性也不错,适合初学者学习和使用。 ... [详细]
  • 本文介绍了一个在线急等问题解决方法,即如何统计数据库中某个字段下的所有数据,并将结果显示在文本框里。作者提到了自己是一个菜鸟,希望能够得到帮助。作者使用的是ACCESS数据库,并且给出了一个例子,希望得到的结果是560。作者还提到自己已经尝试了使用"select sum(字段2) from 表名"的语句,得到的结果是650,但不知道如何得到560。希望能够得到解决方案。 ... [详细]
  • Go Cobra命令行工具入门教程
    本文介绍了Go语言实现的命令行工具Cobra的基本概念、安装方法和入门实践。Cobra被广泛应用于各种项目中,如Kubernetes、Hugo和Github CLI等。通过使用Cobra,我们可以快速创建命令行工具,适用于写测试脚本和各种服务的Admin CLI。文章还通过一个简单的demo演示了Cobra的使用方法。 ... [详细]
  • Java在运行已编译完成的类时,是通过java虚拟机来装载和执行的,java虚拟机通过操作系统命令JAVA_HOMEbinjava–option来启 ... [详细]
  • 本文介绍了Windows操作系统的版本及其特点,包括Windows 7系统的6个版本:Starter、Home Basic、Home Premium、Professional、Enterprise、Ultimate。Windows操作系统是微软公司研发的一套操作系统,具有人机操作性优异、支持的应用软件较多、对硬件支持良好等优点。Windows 7 Starter是功能最少的版本,缺乏Aero特效功能,没有64位支持,最初设计不能同时运行三个以上应用程序。 ... [详细]
  • 怎么在PHP项目中实现一个HTTP断点续传功能发布时间:2021-01-1916:26:06来源:亿速云阅读:96作者:Le ... [详细]
  • 李逍遥寻找仙药的迷阵之旅
    本文讲述了少年李逍遥为了救治婶婶的病情,前往仙灵岛寻找仙药的故事。他需要穿越一个由M×N个方格组成的迷阵,有些方格内有怪物,有些方格是安全的。李逍遥需要避开有怪物的方格,并经过最少的方格,找到仙药。在寻找的过程中,他还会遇到神秘人物。本文提供了一个迷阵样例及李逍遥找到仙药的路线。 ... [详细]
  • 模板引擎StringTemplate的使用方法和特点
    本文介绍了模板引擎StringTemplate的使用方法和特点,包括强制Model和View的分离、Lazy-Evaluation、Recursive enable等。同时,还介绍了StringTemplate语法中的属性和普通字符的使用方法,并提供了向模板填充属性的示例代码。 ... [详细]
  • 本文介绍了Codeforces Round #321 (Div. 2)比赛中的问题Kefa and Dishes,通过状压和spfa算法解决了这个问题。给定一个有向图,求在不超过m步的情况下,能获得的最大权值和。点不能重复走。文章详细介绍了问题的题意、解题思路和代码实现。 ... [详细]
author-avatar
陈陈
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有