zoukankan      html  css  js  c++  java
  • OTP服务器

    defmodule Sequence.Server do
        use GenServer
    
        def handle_call( :next_number, _from, current_number) do
            { :reply, current_number, current_number + 1}  #reply告诉OTP将第二个元素返回给客户端
        end
    end

      use的效果将OTP GenServer的行为添加到当前模块。这样它就可以处理所有的回调函数。这也意味着我们不需要在模块中定义所有的回调函数——该行为定义了所有默认的回调函数。

      当客户端调用服务器时,GenServer调用接下来的hand_call函数。它接受:1、客户端传递给调用的信息。2、客户端的PID。3、服务器状态。    

      其返回一个元组给OTP { :reply, current_number, current_number + 1 },reply告诉OTP需要回复客户端,第二个是返回值,第三个定义了新的状态。该状态子在handle_call下次被调用时作为最后一个参数传入。

      

      启动服务器:

    iex -S mix
    { :ok, pid } = GenServer.start_link(Sequence.Server, 100)    #100是状态,相当于该进程的一个属性。
    
    GenServer.call( pid, :next_number )        # 100
    GenServer.call( pid, :next_number )        # 101

      start_link函数的行为类似于spawn_link。它要求GenServer创建一个新的进程并与我们相关联,并传递了一个状态值进去。返回服务器的pid

      call调用pid进程里的handle_call函数,将其第二个参数(:next_number )与handle_call的第一个参数做匹配。handle_call的第一个参数也可以是元组。

    def handle_call({ :set_number, new_number}, _form, _current_number ) do
        {:reply, new_number, new_number }
    end
    
    然后这样调用
    GenServer.call(pid, {:set_number, 999} )        # 999

    cast

      cast函数调用服务器,但不等待回复。cast发送给handle_cast,由于可能没有相应,所以handle_cast只需要两个参数。放弃了第二个代表客户端pid的参数。其返回元组为{ :noreply, new_state }

    defmodule Sequence.Server do
        use GenServer
    
        def handle_call( :next_number, _from, current_number) do
            { :reply, current_number, current_number + 1}
        end
    
        def handle_cast({:increment_number, delta}, current_number) do
            { :noreply, current_number + delta}
        end
    end
    
    GenServer.call(pid, :next_number)      #100
    GenServer.call(pid, :next_number)    #101
    GenServer.cast(pid, {:increment_number, 200})    # :ok
    GenServer.call(pid, :next_number)      #302

    回调函数

      init(start_arguments)。当GenServer启动服务器时被调用,默认将服务器状态设置为出入参数的值。

      handle_call(request, from, state)。客户端使用GenServer.call(pid, request)时被调用。成功返回{ :reply, result, new_state }

      handle_cast(request, state)。用于响应GenServer.cast(pid, request)。成功的相应是{ :noreply, new_state },也能返回{ :stop, reason, new_state }

      handle_info(info, state)。用于处理call和cast以外的传入消息。

      terminate(reason, state)。当服务器将终止时该函数被调用。

      code_change(from_version, state, extra)。理由OTP替换正在运行的服务器而无需停止整个系统。

      format_status(reason, [pdict, state])。定制服务器的状态显示。

    给进程命名

      启动服务器的时候加上 name:参数 。

    { :ok, pid } = GenServer.start_link(Sequence.Server, 100, name::seq)
    GenServer.call(:seq, :next_number)

    整理接口

      

    defmodule Sequence do
        use GenServer
    
        def start_link(current_number) do
            GenServer.start_link(__MODULE__, current_number, name: __MODULE__)
        end
        
        def next_number do
            GenServer.call __MODULE__, next_number
        end
    
        def increment_number(delta) do
            GenServer.call __MODULE__, {:increment_number, delta}
        end
    
    
        def handle_call( :next_number, _from, current_number) do
            { :reply, current_number, current_number + 1}
        end
    
        def handle_cast({:increment_number, delta}, current_number) do
            { :noreply, current_number + delta}
        end
    end
  • 相关阅读:
    [转载]苹果推送通知服务
    Lovekey
    大数阶乘的位数
    大明A+B
    大数取余
    A+Bcoming
    大数取余(C++)
    验证角谷猜想
    麦森数(转)
    大数阶乘的位数(C++)
  • 原文地址:https://www.cnblogs.com/lr1402585172/p/11512363.html
Copyright © 2011-2022 走看看