博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
(整理)用Elixir做一个多人扑克游戏 4
阅读量:6876 次
发布时间:2019-06-26

本文共 2814 字,大约阅读时间需要 9 分钟。

  hot3.png

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

Sockets

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

defmodule GenPoker.Endpoint do  use Phoenix.Endpoint, otp_app: :gen_poker  socket "/socket", GenPoker.PlayerSocketend

Channels

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

defmodule GenPoker.PlayerSocket do  use Phoenix.Socket  channel "tables:*", GenPoker.TableChannelend

创建socket

defmodule GenPoker.PlayerSocket do  use Phoenix.Socket  transport :websocket, Phoenix.Transports.WebSocket  def connect(%{"playerId" => player_id}, socket) do    {:ok, assign(socket, :player_id, player_id)}  end  def id(socket) do     "players_socket:#{socket.assigns.player_id}"  endend

注册进程

defmodule Poker.Table do  use GenServer  def start_link(table_name, sup, storage, num_seats) do    GenServer.start_link(      __MODULE__,       [table_name, sup, storage, num_seats],       name: via_tuple(table_name)    )  end  defp via_tuple(table) do     {:via, :gproc, {:n, :l, {:table, table}}}  end  def whereis(table) do    :gproc.whereis_name({:n, :l, {:table, table}})  endend

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

module GenPoker.TableChannel do  use GenPoker.Web, :channel  alias Poker.Table  def join("tables:" <> table, _payload, socket) do    {:ok, assign(socket, :table, table)}  end  def handle_in(command, payload, socket)     when command in ~w(sit leave buy_in cash_out deal)   do    table = Table.whereis(socket.assigns.table)    arguments = [table, socket.assigns.player_id] ++ payload    result = apply(Table, String.to_atom(command), arguments)    if result == :ok do      broadcast! socket, "update", Table.get_state(table)    end    {:reply, result, socket}  endend

对于客户端的join请求,我们有不同的回复。在JavaScript中可以这样写:

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

发送初始的state

def join("tables:" <> table, _payload, socket) do  state = table |> Table.whereis |> Table.get_state  push socket, "update", state  {:ok, assign(socket, :table, table)}end

使用handle_info

def join("tables:" <> table, _payload, socket) do  send self, :after_join  {:ok, assign(socket, :table, table)}enddef handle_info(:after_join, socket) do  state = socket.assigns.table |> Table.whereis |> Table.get_state  push socket, "update", state  {:noreply, socket}enddef handle_info(_, socket) do  {:noreply, socket}end

拦截消息

def handle_out("update", state, socket) do  push socket, "update", hide_other_hands(state, socket)  {:noreply, socket}enddefp hide_other_hands(state, socket) do  player_id = socket.assigns.player_id  hide_hand_if_current_player = fn    %{id: ^player_id} = player -> player    player -> Map.delete(player, :hand)  end  update_in(state.players, fn players ->    Enum.map(players, hide_hand_if_current_player)  end)end

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

你可能感兴趣的文章
vue服务器端渲染(SSR)实战
查看>>
「原码 反码 补码 移码」一探究竟(中)
查看>>
CSS 你到底有多少长度单位?
查看>>
Linux Shell脚本系列之二
查看>>
设计模式--代理模式(Proxy Pattern)
查看>>
稀疏数组
查看>>
HTML5 标签 canvas
查看>>
react-router@4.0 使用方法和源码分析
查看>>
Flutter简介
查看>>
组织级敏捷转型的四个阶段
查看>>
「数据游戏」:使用 LSTM 模型预测三天后单股收盘价
查看>>
vuex持久化插件-解决浏览器刷新数据消失问题
查看>>
Vue-cli3 项目在安卓低版本系统和 IE 上白屏问题解决
查看>>
并发-7-同步容器和ConcurrentHashMap
查看>>
小程序白屏问题和内存研究
查看>>
React安装:
查看>>
从0开始搭建微信小程序(前后端)的全过程
查看>>
Code Coverage API plugin 一个新的代码覆盖率插件
查看>>
DTCC 2019 | 深度解码阿里数据库实现 数据库内核——基于HLC的分布式事务实现深度剖析...
查看>>
【思维导图】NoSQL分布式模型
查看>>