`
cnDenis
  • 浏览: 100323 次
  • 来自: 广州
社区版块
存档分类
最新评论

初识Erlang,Hello World(4)

阅读更多

初识Erlang,Hello World(4)

by cnDenis http://cndenis.iteye.com 2013年3月30日

前几节的Hello world都是自言自语,今天试试对着别人说。首先是在本机上各个进程之间, 然后是在网络上不同机器之间。

进程间的消息:单向接收

Erlang里可以很方便地创建进程,这种进程是超轻量级的,运行于erlang虚拟机内部的, 而与操作系统的进程管理无关的(也就是说你在任务管理器中只会见到一个Erlang进程), Erlang内的进程创建开销很小,创建一个进程所需的时间仅为微秒级,内存消耗也很少, 一台机上运行数以千计的进程也没问题。

进程之间使用消息进行通讯。示例如下:

hw15srv() ->
    receive
        {name, Name} -> 
            io:format("Hello ~p ~n", [Name]),
            hw15srv()
    end.

hw15() ->
    Pid = spawn(fun hw15srv/0),
    Pid ! {name, "alice"},
    Pid ! {name, "Bob"}.

hw15/0首先是使用spawn命令启动了一个hw15srv/0进程,。这个命令会返回 所启动的进程的pid,也就是进程的标识符。然后使用!向它发送消息。

spawn命令有几种用法,对于上例,以下几种方式都可以

spawn(fun hw15srv/0)
spawn(fun() -> hw15srv() end)
spawn(?MODULE, hw15srv, [])

要注意的是,第三种用法(也叫MFA法,即模块、函数、参数法)进行调用的话, 这个被调用的函数(即示例中的hw15srv)必须要export出来,即便是写在同一个文件中。

hw15srv/0的作用是接收其他进程给他发的消息,并显示出来。接收消息使用receive, 格式有点象case,先是对收到的消息进行模式匹配,如果匹配的话,该项->后的语句。

发送消息的进程和接收消息的进程需要协调好消息的格式,这段程序中,消息是一个元组, 元组的第一个元素是原子name,(一般习惯中erlang中的元组的第一个元素用一个原子 作元组的命名),第二个元素是一个字符串。

hw15srv/0用的是所谓尾递归服务器的写法,语句段的最后一行写上递归函数名, 象这样的服务器一定要符合尾递归的要求,不然的话运行一段时间服务器就会把内存塞爆。

进程间的消息:相互对话

上一段程序中,hw15srv/0是只收不发的,别人对它说什么,它都没有响应。如果需要 有回应的话,可以这么写:

hw16srv() ->
    receive 
        {From, {name, Name}} ->
            io:format("Server receive: ~p ~n", [Name]),
            From ! {self(), {reply, "Welcome, " ++ Name}},
            hw16srv()
    end.

hw16() ->
    Pid = spawn(fun hw16srv/0),
    Sid = self(),
    Pid ! {Sid, {name, "alice"}},
    receive
        {Pid, {reply, Msg}} ->
            io:format("Client receive: ~p ~n", [Msg])
    end.

用到的关键字和上一段程序是一样的:创建进程spawn,发送消息!,接收消息receive, 区别仅在于消息的格式。本段程序在消息的前面加上客户端进程的pid,让服务端进程知道 消息是由哪个进程发过来的。Erlang似乎没有获知消息来源的机制,因此需要手工把发送方 的pid写到消息中,方便接收方使用。

hw16/0中,使用了self()来获得本进程的pid,然后本进程pid填到消息中,发给 服务端,然后等待服务端发过来的消息,收到后就显示出来。

hw16srv/0中则是接收消息,然后提取对方发过来的名字,在前面加上"welcome",然后 发回给客户端。

进程间的消息:RPC

RPC是远程过程调用的缩写,也就是让另一个地方的程序帮你执行,然后把结果返回给你。 Erlang中的发送请求和等待回应可以封装为一个rpc/2的函数:

rpc(Pid, Request) ->
    Pid ! {self(), Request},
    receive
        {Pid, Response} ->
            Response
    end.

hw16b() ->
    Pid = spawn(fun hw16srv/0),
    {reply, Reply} = rpc(Pid, {name, "alice"}),
    io:format("Client receive: ~p ~n", [Reply]).

rpc/2把发送请求和等待回应包装起来,用起来更方便了

进程间的消息:引用

上面的rpc有个两个问题:第一个问题,是当传入的第一个参数不是一个pid,而是一个注 册了的进程名,信息虽然也能发出去,返回的信息却是pid而不是注册名,无法匹配 {Pid, Response} ,因而函数会永远等待下去而不返回。第二个问题,如果本线程给远 方线程发送了几个请求,对方发回了几个回复,那就搞不清哪个回复是对应哪个请求的了。 解决这两个问题的方法是使用一个“引用”,如下:

rpc2(Pid, Request) ->
    Ref = make_ref(),
    Pid ! {{self(), Ref}, Request},
    receive
        {Ref, Reply} ->
            Reply
    end.

hw18srv() ->
    receive 
        {{From, Ref}, {name, Name}} ->
            io:format("Server receive: ~p ~n", [Name]),
            From ! {Ref, {reply, "Welcome, " ++ Name}},
            hw16srv()
    end.

hw18() ->
    Pid = spawn(fun hw18srv/0),
    {reply, Reply} = rpc2(Pid, {name, "alice"}),
    io:format("Client receive: ~p ~n", [Reply]).

rpc2/2就用了 make_ref() 来生成一个唯一的“引用”,make_ref/0生成的引用几乎 是不会重复的,文档上的说明是要2E82次调用之后才会发生重复,这实际上是不可能的。

(在这里bs一下《Erlang编程指南》这本书的中文翻译,译得像机翻也就算了,错误还不少, 像这个82在那本书上就被写成了28,我看书时还在怀疑,现代计算机进行2E28次运算, 不就是几秒的事,这make_ref到底行不行。(在211页))

分享到:
评论

相关推荐

    HelloWorld-main.zip

    【HelloWorld-main.zip】是一个包含了多种编程语言的“Hello, World!”程序源代码的压缩包。这个资源对于初学者来说非常有价值,因为它涵盖了从传统到现代的多种编程语言,可以帮助新接触编程的人快速理解每种语言的...

    各种程序语言的Hello_World程序

    module HelloWorld (main) where main = putStrLn "Hello World!\n" ``` **解析:** - Haskell是一种纯函数式编程语言。 - `module`定义模块。 - `putStrLn`用于输出字符串。 #### Icon ```icon procedure main() ...

    ErLang 23.3.4 安装包,windosw版本64位安装包

    ErLang 23.3.4 安装包,windosw版本64位安装包

    RabbitMQ hello world源码

    "RabbitMQ hello world源码"通常是指一个简单的示例,用于展示如何在RabbitMQ中发送和接收消息。这个例子可以帮助初学者快速理解RabbitMQ的基本工作原理和API使用。 **发送端(Producer)** 在RabbitMQ的"hello ...

    esl-erlang_23.0_windows_amd64.exe rabbitmq-server-3.8.4.exe

    esl-erlang_23.0和rabbitmq-3.8.4windows版本 直接下载安装就行,可以直接下载就可安装,非常的方便...4. erlang安装后要检查能否编译成功一个helloworld文件。 5. rabbitMQ无法安装插件时非常有可能是erlang出问题了。

    RabbitMQ-HelloWorld:RabbitMQ的Hello World示例

    在RabbitMQ的"Hello World"示例中,首先要做的是建立一个到RabbitMQ服务器的连接,并创建一个信道。信道是RabbitMQ中的工作线程,通过它我们实际执行发布和消费消息的操作。 ```csharp using RabbitMQ.Client; ...

    RabbitMQ系列(一)入门Helloworld

    **RabbitMQ系列(一)入门Helloworld** RabbitMQ是一种开源的消息代理和队列服务器,它基于AMQP(Advanced Message Queuing Protocol)协议,广泛应用于分布式系统中的异步处理和解耦。在这个系列的第一部分,我们...

    RabbitMQ 3.8.9 + erlang23.1.4 windows 安装包

    先安装erlang,设置环境变量“ERLANG_HOME={erlang安装路径}”,添加“%ERLANG_HOME%\bin”到系统变量Path中 再安装RabbitMQ 再到RabbitMQ安装目录下启动cmd,运行“rabbitmq-plugins enable rabbitmq_management” ...

    erlang学习1.pdf

    **运行程序**:启动Erlang Shell,并调用`helloworld:sayhello()`执行程序。 #### 三、TCP客户端实现 - **基本需求**:实现一个简单的TCP客户端,可以连接至Web服务器并显示服务器返回的数据。 - **实现过程**: ...

    erlang编程 Introducing Erlang

    ### 4. 链接与监控 Erlang中的链接(Linking)和监控(Monitoring)机制允许进程间建立关系,以便在另一进程崩溃时得到通知。链接用于追踪相关进程的状态,而监控则可以观察进程的生存状态。 ### 5. 消息传递 ...

    Erlang/OTP 26.2.1

    Erlang/OTP 26.2.1,Erlang,OTP,26.2.1

    erlang25.0 windows版本

    4. **验证**:安装完成后,打开命令行窗口并输入`erl`,如果Erlang成功安装,你应该能看到Erlang的shell(REPL)启动。 Erlang 25.0版本可能包含以下改进和新特性: 1. **性能优化**:新版本通常会对语言性能进行...

    erlang_版本24.3.4.4

    4. **构建和测试**:执行`make`命令开始编译Erlang。这个过程可能需要一些时间,因为它会编译整个Erlang虚拟机和标准库。编译完成后,你可以通过运行`make tests`来验证Erlang的正确性。 5. **安装**:最后,使用`...

    erlang-20.3.4

    erlang-20.3.4 rabbitmq3.7.4 yum安装erlang yum安装rabbitmq

    erlang资源

    4. **分布式编程**:Erlang进程可以分布在多个节点上,实现分布式系统的构建。书可能讲解了如何进行节点间通信、分布式数据管理和负载均衡。 5. **模式匹配**:Erlang的函数定义允许模式匹配,使得代码更加简洁和可...

    erlang22最新下载包

    4. **库和工具的更新**:OTP中的各种库(如Mnesia数据库、ERTS(Erlang Run-Time System)和其他并发工具)可能进行了升级,以适应新的需求和改进功能。 5. **并发与分布式系统支持**:Erlang以其轻量级进程和消息...

    Erlang官网下载过慢

    4. 镜像站点:寻找Erlang的镜像站点,这些站点通常位于地理位置更近的地方,下载速度会更快。 标签中提到了“Erlang Rabbit 异步通讯”,这意味着讨论的重点是Erlang如何与RabbitMQ结合实现异步通信。RabbitMQ是一...

    可在ubuntu上安装erlang的deb包

    4,不同机器安装速度不一样,耐心等待; 5,安装成功,你谢谢deb包的开发者,然后代开ubuntu的terminal,输入erl命令即可运行。 6,安装失败,你骂我好了,并把你的ubunt版本、是否是在虚拟机和其下的虚拟机软件...

    Erlang26-windows安装包

    RabbitMQ version Minimum required Erlang/OTP Maximum supported Erlang/OTP Notes 3.13.0 26.0 26.2.x The 3.13 release series is compatible wtih Erlang 26. OpenSSL 3 support in Erlang is considered to ...

    xiandiao_erlang_Erlang课后习题_

    4. **容错性**:Erlang的进程模型鼓励设计出可以失败并从中恢复的系统。当一个进程出错时,它不会影响到其他进程,这种特性使得Erlang非常适合构建高可用的服务。 5. **简洁的错误处理**:Erlang使用“let it crash...

Global site tag (gtag.js) - Google Analytics