热门标签 | 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



推荐阅读
  • Spring Boot 中配置全局文件上传路径并实现文件上传功能
    本文介绍如何在 Spring Boot 项目中配置全局文件上传路径,并通过读取配置项实现文件上传功能。通过这种方式,可以更好地管理和维护文件路径。 ... [详细]
  • Java高并发与多线程(二):线程的实现方式详解
    本文将深入探讨Java中线程的三种主要实现方式,包括继承Thread类、实现Runnable接口和实现Callable接口,并分析它们之间的异同及其应用场景。 ... [详细]
  • 本指南介绍了如何在ASP.NET Web应用程序中利用C#和JavaScript实现基于指纹识别的登录系统。通过集成指纹识别技术,用户无需输入传统的登录ID即可完成身份验证,从而提升用户体验和安全性。我们将详细探讨如何配置和部署这一功能,确保系统的稳定性和可靠性。 ... [详细]
  • 本文探讨了资源访问的学习路径与方法,旨在帮助学习者更高效地获取和利用各类资源。通过分析不同资源的特点和应用场景,提出了多种实用的学习策略和技术手段,为学习者提供了系统的指导和建议。 ... [详细]
  • 本文详细解析了JSONP(JSON with Padding)的跨域机制及其工作原理。JSONP是一种通过动态创建``标签来实现跨域请求的技术,其核心在于利用了浏览器对``标签的宽松同源策略。文章不仅介绍了JSONP的产生背景,还深入探讨了其具体实现过程,包括如何构造请求、服务器端如何响应以及客户端如何处理返回的数据。此外,还分析了JSONP的优势和局限性,帮助读者全面理解这一技术在现代Web开发中的应用。 ... [详细]
  • 深入解析Gradle中的Project核心组件
    在Gradle构建系统中,`Project` 是一个核心组件,扮演着至关重要的角色。通过使用 `./gradlew projects` 命令,可以清晰地列出当前项目结构中包含的所有子项目,这有助于开发者更好地理解和管理复杂的多模块项目。此外,`Project` 对象还提供了丰富的配置选项和生命周期管理功能,使得构建过程更加灵活高效。 ... [详细]
  • Hadoop的文件操作位于包org.apache.hadoop.fs里面,能够进行新建、删除、修改等操作。比较重要的几个类:(1)Configurati ... [详细]
  • 本文详细介绍了 Pentaho Kettle 中 RowMetaInterface.writeMeta 方法的使用,并提供了多个代码示例,帮助开发者更好地理解和应用该方法。 ... [详细]
  • 本文详细介绍了Java反射机制的基本概念、获取Class对象的方法、反射的主要功能及其在实际开发中的应用。通过具体示例,帮助读者更好地理解和使用Java反射。 ... [详细]
  • Python 伦理黑客技术:深入探讨后门攻击(第三部分)
    在《Python 伦理黑客技术:深入探讨后门攻击(第三部分)》中,作者详细分析了后门攻击中的Socket问题。由于TCP协议基于流,难以确定消息批次的结束点,这给后门攻击的实现带来了挑战。为了解决这一问题,文章提出了一系列有效的技术方案,包括使用特定的分隔符和长度前缀,以确保数据包的准确传输和解析。这些方法不仅提高了攻击的隐蔽性和可靠性,还为安全研究人员提供了宝贵的参考。 ... [详细]
  • 本文探讨了如何在C#应用程序中通过选择ComboBox项从MySQL数据库中检索数据值。具体介绍了在事件处理方法 `comboBox2_SelectedIndexChanged` 中可能出现的常见错误,并提供了详细的解决方案和优化建议,以确保数据能够正确且高效地从数据库中读取并显示在界面上。此外,还讨论了连接字符串的配置、SQL查询语句的编写以及异常处理的最佳实践,帮助开发者避免常见的陷阱并提高代码的健壮性。 ... [详细]
  • CTF竞赛中文件上传技巧与安全绕过方法深入解析
    CTF竞赛中文件上传技巧与安全绕过方法深入解析 ... [详细]
  • 本文深入探讨了 Git 与 SVN 的高效使用技巧,旨在帮助开发者轻松应对版本控制中的各种挑战。通过详细解析两种工具的核心功能与最佳实践,读者将能够更好地掌握版本管理的精髓,提高开发效率。 ... [详细]
  • 在探讨 AS3 中的数据深度复制技术时,本文详细介绍了实现数据深度克隆的有效方法。通过对比多种方案,最终确定了一种高效且可靠的实现方式,所有代码均来源于公开资源,确保了方法的实用性和可操作性。 ... [详细]
  • Android目录遍历工具 | AppCrawler自动化测试进阶(第二部分):个性化配置详解
    终于迎来了“足不出户也能为社会贡献力量”的时刻,但有追求的测试工程师绝不会让自己的生活变得乏味。与其在家消磨时光,不如利用这段时间深入研究和提升自己的技术能力,特别是对AppCrawler自动化测试工具的个性化配置进行详细探索。这不仅能够提高测试效率,还能为项目带来更多的价值。 ... [详细]
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社区 版权所有