Chinaunix首页 | 论坛 | 博客
  • 博客访问: 101966
  • 博文数量: 18
  • 博客积分: 681
  • 博客等级: 中士
  • 技术积分: 295
  • 用 户 组: 普通用户
  • 注册时间: 2010-04-17 13:33
文章分类
文章存档

2012年(8)

2011年(10)

分类: Python/Ruby

2012-10-07 13:24:33

现有一个Erlang套接字编程的例子,监控树如上图。tr_server监听并监创建套接字,打印客户端发送到服务器的数据,并且能创建新tr_server进程继续监听套接字连接;tr_server_sup是个simple_one_for_one的supervisor进程,能够动态地创建tr_server进程。

tr_server

-module(tr_server).

-behaviour(gen_server).

-export([start_link/1,

         start_link_v2/1]).

-export([init/1,

         handle_cast/2,

         handle_info/2,

         terminate/2]).

-record(state, {lsock,socket}).

start_link(LSock) ->

    gen_server:start_link(?MODULE, [LSock], []).

init([LSock]) ->

    send(self(), listen),

    {ok, #state{lsock=LSock}}.

handle_cast(listen, #state{lsock=LSock}) ->

    %%{ok, LSock} = gen_tcp:listen(Port, [{active, once}]),

    {ok, Socket} = gen_tcp:accept(LSock),

    tr_server_sup:start_child(LSock),

    {noreply, #state{socket=Socket}}.

handle_info({tcp, _Port, Packet}, #state{socket=Socket}) ->

    io:format("~p~n", [Packet]),

    inet:setopts(Socket, [{active, once}]),

    {noreply, #state{socket=Socket}}.

terminate(_Reason, _State) ->

    ok.

send(Pid, Msg) ->

    gen_server:cast(Pid, Msg).

tr_server的初始化非常简单,仅仅是给自身发送个listen异步消息,这是因为进程的启动是个原子操作,为了避免tr_server的进程创建时间过长,因此把等待客户端连接的动作放到进程启动之后再处理;

客户端与服务端通过套接字的数据会以erlang消息的形式发送给套接字处理进程,其标签为{tcp, Port, RawData},因此必须在handle_info中接收和处理通过套接字接收到的数据;

在Erlang中,套接字active模式主要有三种,这里使用的是once,三种模式的简介如下:

active

说明

true

当套接字接收到数据时,就直接发送给处理进程

false

当套接字接收到数据时,不主动把数据发送给处理进程,需要处理进程从套接字中取

once

当套接字接收到数据时,如果是第一次,就把数据发送给处理进程,否则,不发送(处理程序处理完一次时,可以调用inet:setopts再次把active设置为once)

tr_server_sup

-module(tr_server_sup).

-behaviour(supervisor).

-export([start_link/0,

         start_child/1]).

-export([init/1]).

-define(CHILD(Id, Mod, Type, Args), {Id, {Mod, start_link, Args},

                                     temporary, brutal_kill, Type, [Mod]}).

start_link() ->

    supervisor:start_link({local, ?MODULE}, ?MODULE, []).

start_child(LSock)->

    supervisor:start_child(?MODULE, [LSock]).

init([]) ->

    {ok, {{simple_one_for_one, 0, 1},

          [?CHILD(tr_server, tr_server, worker, [])]}}.

tr_server_sup是个simple_one_for_one进程,其启动时不启动进程,需要调用tr_server_sup:start_child(LSock)动态地创建tr_server worker进程;

启动tr_server_sup

启动tr_server_sup时需要启动第一个tr_server进程,之后tr_server会调用tr_server_sup动态地创建tr_server进程。




阅读(3218) | 评论(1) | 转发(1) |
0

上一篇:记一次程序的抽象

下一篇:没有了

给主人留下些什么吧!~~

最大行业软件2012-12-01 10:36:00

PTC Creo Elements/Pro 5.0 M070 Working for Win32-ISO 1DVD(最新多语言正式版包括简、繁体中文)

PTC Creo Elements/Pro 5.0 M070 Working for Win64-ISO 1DVD

PTC Creo Elements View (ex Product View) v10 F000 build 93 Pro Multilanguage Win32 1CD

PTC Creo Elements View (ex Product View) v10 F000 build 93 Pro Multilanguage Win64 1CD

 

PTC Pro/E WildFire+Pro/Mechancia 4.0 M110 Working for Win32-ISO 1DVD(最新多语言正式版包括简、繁体中文)

PTC Pro/E Wil