EventMachine简明手册

EventMachine是Ruby的事件驱动的网络库,类似于Python的Twisted,某些方面也类似于Erlang/OTP的gen_server模块。本文翻译自Jesse Farmer的An EventMachine Tutorial

为什么使用EventMachine

EventMachine满足两方面核心需求。首先,因为EventMachine是reactor pattern的实现,它隔离了网络逻辑和应用逻辑。这意味着你无需担心去处理低层网络连接和socket逻辑,只要写好网络事件的回调函数就可以了。

其次,EventMachine是轻量级的,并且支持原生的系统级网络功能。这意味着Ruby的运行速度不成问题:与性能攸关的部分是用C/C++写的,并且使用操作系统提供的最佳模式(例如Linux的epoll)。

简言之,EventMachine使Ruby编写网络程序变得非常灵活简单。谁不愿意这样做呢?

安装EventMachine

EventMachine以Ruby gem的方式发布,叫做eventmachine。运行gem install eventmachine就可以安装好它。

注意EventMachine在安装时需要系统里有C++编译器。

使用EventMachine

即学即用吧。

echo服务

echo服务是传统的Unix服务,它接受进来的网络连接,把客户端发过来的东西,再逐字节的发回去。使用EventMachine编写它是如此容易。

#!/usr/bin/env ruby

require ‘rubygems’
require ‘eventmachine’

module EchoServer
    def receive_data(data)
        send_data(data)
    end
end

EventMachine::run do
    host = ‘0.0.0.0’
    port = 8080
    EventMachine::start_server host, port, EchoServer
    puts “Started EchoServer on #{host}:#{port}…”
end

运行上述程序后,echo服务器侦听在8080端口,接受所有进来连接。让我们进一步分析。

首先看看代码底部的EventMachine::run,它启动了一个事件循环。它期待一个block作为参数输入,在该block里,我们启动socket客户端或服务器,它们一直在循环里运行,直到调用EventMachine::stop_event_loop后,才会终结。

我们使用EventMachine::start_server启动echo服务。前2个参数是主机名和端口,0.0.0.0:8080意味着echo服务器在本机的所有网络地址的8080端口侦听。

第3个参数就是处理器。处理器典型的就是一个Ruby模块,在里面定义了相应的回调函数。不直接使用回调函数是为了避免污染全局名字空间。Echo服务器仅仅定义了receive_data函数,无论何时我们从网络连接里接受到数据,该函数就会被调用。

最后,在EchoServer里只要EventMachine调用了receive_data,我们就调用send_data将数据发送回去。

HTTP客户端

除了用EventMachine::start_server创建服务器外,EventMachine也可以用来创建socket客户端,使用 EventMachine::connect方法。如下这个程序连接到一个HTTP服务器,并且打印输出它接受到的HTTP头部。

#!/usr/bin/env ruby

require ‘rubygems’
require ‘eventmachine’

module HttpHeaders
    def post_init
      send_data “GET /\r\n\r\n”
      @data = “”
    end

    def receive_data(data)
      @data << data
    end

    def unbind
      if @data =~ /[\n][\r]*[\n]/m
        $`.each {|line| puts “>>> #{line}” }
      end

      EventMachine::stop_event_loop
    end
end

EventMachine::run do
    EventMachine::connect ‘microsoft.com’, 80, HttpHeaders
end

上述代码假如将microsoft.com改为ARGV[0],在命令行传入任何网站地址并运行,就可以得到它们的返回头部。

这里有个新的回调函数post_init,一旦连接建立后它就会调用。所谓连接建立,假如是客户端,就是与服务器的连接,反之如果是服务器,那就是与客户端的连接。

我们也使用了unbind回调函数,任何一端关闭连接,都会调用该函数。在我们的示例里是服务器关闭了连接,因为它已经发送完了所有数据。假如你在编写一个服务器,那么可能是客户端关闭了连接。

unbind和post_init是互补的2个函数,前者在连接关闭时调用,后者在连接建立时调用。我也不清楚为何它们如此命名,总之能用就行了。

就这3个主要的回调函数:在连接建立时、在接受数据时、在关闭连接时,做一些事情。外加一个send_data函数用来发送数据。其他的方法无非是上述方法的变种。

进一步阅读

本简明手册只描述了基本的东西,事实上EventMachine可以做很多事。更多的技术细节,推荐阅读EventMachine的官方网站,以及Rdoc文档。

还有一篇文章描述了使用EventMachine和Jabber协议来创建一个Jabber客户端,也值得一读。

此条目发表在Common分类目录,贴了标签。将固定链接加入收藏夹。