eventmachine 0.3.1
Sign up to get free protection for your applications and to get access to all the features.
- data/COPYING +281 -0
- data/README +69 -0
- data/RELEASE_NOTES +18 -0
- data/doc/classes/Echo.html +180 -0
- data/doc/classes/Echo.src/M000033.html +23 -0
- data/doc/classes/Echo.src/M000034.html +19 -0
- data/doc/classes/Echo.src/M000035.html +19 -0
- data/doc/classes/Echo.src/M000036.html +18 -0
- data/doc/classes/EventMachine.html +369 -0
- data/doc/classes/EventMachine.src/M000002.html +24 -0
- data/doc/classes/EventMachine.src/M000003.html +24 -0
- data/doc/classes/EventMachine.src/M000004.html +26 -0
- data/doc/classes/EventMachine.src/M000005.html +21 -0
- data/doc/classes/EventMachine.src/M000006.html +23 -0
- data/doc/classes/EventMachine.src/M000007.html +28 -0
- data/doc/classes/EventMachine.src/M000008.html +20 -0
- data/doc/classes/EventMachine.src/M000009.html +19 -0
- data/doc/classes/EventMachine.src/M000010.html +18 -0
- data/doc/classes/EventMachine.src/M000011.html +18 -0
- data/doc/classes/EventMachine/Connection.html +341 -0
- data/doc/classes/EventMachine/Connection.src/M000020.html +19 -0
- data/doc/classes/EventMachine/Connection.src/M000021.html +17 -0
- data/doc/classes/EventMachine/Connection.src/M000022.html +18 -0
- data/doc/classes/EventMachine/Connection.src/M000023.html +17 -0
- data/doc/classes/EventMachine/Connection.src/M000024.html +18 -0
- data/doc/classes/EventMachine/Connection.src/M000025.html +18 -0
- data/doc/classes/EventMachine/Connection.src/M000026.html +18 -0
- data/doc/classes/EventMachine/Connection.src/M000027.html +18 -0
- data/doc/classes/EventMachine/Connection.src/M000028.html +17 -0
- data/doc/classes/EventMachine/Connection.src/M000029.html +18 -0
- data/doc/classes/EventMachine/Connection.src/M000030.html +18 -0
- data/doc/classes/EventMachine/Connection.src/M000031.html +18 -0
- data/doc/classes/EventMachine/Connection.src/M000032.html +18 -0
- data/doc/classes/EventMachine/ConnectionAlreadyBound.html +111 -0
- data/doc/classes/EventMachine/ConnectionNotBound.html +111 -0
- data/doc/classes/EventMachine/Connections.html +292 -0
- data/doc/classes/EventMachine/Connections.src/M000012.html +20 -0
- data/doc/classes/EventMachine/Connections.src/M000013.html +23 -0
- data/doc/classes/EventMachine/Connections.src/M000014.html +23 -0
- data/doc/classes/EventMachine/Connections.src/M000015.html +24 -0
- data/doc/classes/EventMachine/Connections.src/M000016.html +19 -0
- data/doc/classes/EventMachine/Connections.src/M000017.html +21 -0
- data/doc/classes/EventMachine/Connections.src/M000018.html +19 -0
- data/doc/classes/EventMachine/Connections.src/M000019.html +20 -0
- data/doc/classes/EventMachine/EventCodes.html +133 -0
- data/doc/classes/EventMachine/NoConnectionMade.html +111 -0
- data/doc/classes/EventMachine/NoHandlerForAcceptedConnection.html +111 -0
- data/doc/classes/EventMachine/NoServerCreated.html +111 -0
- data/doc/classes/EventMachine/TimerNotInstalled.html +111 -0
- data/doc/classes/EventMachine/TooManyAcceptors.html +111 -0
- data/doc/classes/EventMachine/TooManyTimersPending.html +111 -0
- data/doc/classes/EventMachine/UnknownTimerFired.html +111 -0
- data/doc/classes/Zzz.html +131 -0
- data/doc/classes/Zzz.src/M000001.html +18 -0
- data/doc/created.rid +1 -0
- data/doc/files/binder_cpp.html +101 -0
- data/doc/files/ed_cpp.html +101 -0
- data/doc/files/em_cpp.html +101 -0
- data/doc/files/event_machine_rb.html +118 -0
- data/doc/files/g_rb.html +108 -0
- data/doc/files/lib/eventmachine_rb.html +114 -0
- data/doc/files/libmain_cpp.html +101 -0
- data/doc/files/sigs_cpp.html +101 -0
- data/doc/files/tests/testem_rb.html +110 -0
- data/doc/fr_class_index.html +41 -0
- data/doc/fr_file_index.html +35 -0
- data/doc/fr_method_index.html +62 -0
- data/doc/index.html +24 -0
- data/ext/libeventmachine.so +0 -0
- data/lib/eventmachine.rb +631 -0
- data/tests/testem.rb +5 -0
- metadata +121 -0
@@ -0,0 +1,41 @@
|
|
1
|
+
|
2
|
+
<?xml version="1.0" encoding="iso-8859-1"?>
|
3
|
+
<!DOCTYPE html
|
4
|
+
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
5
|
+
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
6
|
+
|
7
|
+
<!--
|
8
|
+
|
9
|
+
Classes
|
10
|
+
|
11
|
+
-->
|
12
|
+
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
13
|
+
<head>
|
14
|
+
<title>Classes</title>
|
15
|
+
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
|
16
|
+
<link rel="stylesheet" href="rdoc-style.css" type="text/css" />
|
17
|
+
<base target="docwin" />
|
18
|
+
</head>
|
19
|
+
<body>
|
20
|
+
<div id="index">
|
21
|
+
<h1 class="section-bar">Classes</h1>
|
22
|
+
<div id="index-entries">
|
23
|
+
<a href="classes/Echo.html">Echo</a><br />
|
24
|
+
<a href="classes/EventMachine.html">EventMachine</a><br />
|
25
|
+
<a href="classes/EventMachine/Connection.html">EventMachine::Connection</a><br />
|
26
|
+
<a href="classes/EventMachine/ConnectionAlreadyBound.html">EventMachine::ConnectionAlreadyBound</a><br />
|
27
|
+
<a href="classes/EventMachine/ConnectionNotBound.html">EventMachine::ConnectionNotBound</a><br />
|
28
|
+
<a href="classes/EventMachine/Connections.html">EventMachine::Connections</a><br />
|
29
|
+
<a href="classes/EventMachine/EventCodes.html">EventMachine::EventCodes</a><br />
|
30
|
+
<a href="classes/EventMachine/NoConnectionMade.html">EventMachine::NoConnectionMade</a><br />
|
31
|
+
<a href="classes/EventMachine/NoHandlerForAcceptedConnection.html">EventMachine::NoHandlerForAcceptedConnection</a><br />
|
32
|
+
<a href="classes/EventMachine/NoServerCreated.html">EventMachine::NoServerCreated</a><br />
|
33
|
+
<a href="classes/EventMachine/TimerNotInstalled.html">EventMachine::TimerNotInstalled</a><br />
|
34
|
+
<a href="classes/EventMachine/TooManyAcceptors.html">EventMachine::TooManyAcceptors</a><br />
|
35
|
+
<a href="classes/EventMachine/TooManyTimersPending.html">EventMachine::TooManyTimersPending</a><br />
|
36
|
+
<a href="classes/EventMachine/UnknownTimerFired.html">EventMachine::UnknownTimerFired</a><br />
|
37
|
+
<a href="classes/Zzz.html">Zzz</a><br />
|
38
|
+
</div>
|
39
|
+
</div>
|
40
|
+
</body>
|
41
|
+
</html>
|
@@ -0,0 +1,35 @@
|
|
1
|
+
|
2
|
+
<?xml version="1.0" encoding="iso-8859-1"?>
|
3
|
+
<!DOCTYPE html
|
4
|
+
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
5
|
+
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
6
|
+
|
7
|
+
<!--
|
8
|
+
|
9
|
+
Files
|
10
|
+
|
11
|
+
-->
|
12
|
+
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
13
|
+
<head>
|
14
|
+
<title>Files</title>
|
15
|
+
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
|
16
|
+
<link rel="stylesheet" href="rdoc-style.css" type="text/css" />
|
17
|
+
<base target="docwin" />
|
18
|
+
</head>
|
19
|
+
<body>
|
20
|
+
<div id="index">
|
21
|
+
<h1 class="section-bar">Files</h1>
|
22
|
+
<div id="index-entries">
|
23
|
+
<a href="files/binder_cpp.html">binder.cpp</a><br />
|
24
|
+
<a href="files/ed_cpp.html">ed.cpp</a><br />
|
25
|
+
<a href="files/em_cpp.html">em.cpp</a><br />
|
26
|
+
<a href="files/event_machine_rb.html">event_machine.rb</a><br />
|
27
|
+
<a href="files/g_rb.html">g.rb</a><br />
|
28
|
+
<a href="files/lib/eventmachine_rb.html">lib/eventmachine.rb</a><br />
|
29
|
+
<a href="files/libmain_cpp.html">libmain.cpp</a><br />
|
30
|
+
<a href="files/sigs_cpp.html">sigs.cpp</a><br />
|
31
|
+
<a href="files/tests/testem_rb.html">tests/testem.rb</a><br />
|
32
|
+
</div>
|
33
|
+
</div>
|
34
|
+
</body>
|
35
|
+
</html>
|
@@ -0,0 +1,62 @@
|
|
1
|
+
|
2
|
+
<?xml version="1.0" encoding="iso-8859-1"?>
|
3
|
+
<!DOCTYPE html
|
4
|
+
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
5
|
+
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
6
|
+
|
7
|
+
<!--
|
8
|
+
|
9
|
+
Methods
|
10
|
+
|
11
|
+
-->
|
12
|
+
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
13
|
+
<head>
|
14
|
+
<title>Methods</title>
|
15
|
+
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
|
16
|
+
<link rel="stylesheet" href="rdoc-style.css" type="text/css" />
|
17
|
+
<base target="docwin" />
|
18
|
+
</head>
|
19
|
+
<body>
|
20
|
+
<div id="index">
|
21
|
+
<h1 class="section-bar">Methods</h1>
|
22
|
+
<div id="index-entries">
|
23
|
+
<a href="classes/EventMachine/Connections.html#M000019">accept_connection (EventMachine::Connections)</a><br />
|
24
|
+
<a href="classes/EventMachine.html#M000004">add_periodic_timer (EventMachine)</a><br />
|
25
|
+
<a href="classes/EventMachine/Connections.html#M000017">add_timer (EventMachine::Connections)</a><br />
|
26
|
+
<a href="classes/EventMachine.html#M000003">add_timer (EventMachine)</a><br />
|
27
|
+
<a href="classes/EventMachine.html#M000008">add_timer (EventMachine)</a><br />
|
28
|
+
<a href="classes/EventMachine/Connection.html#M000031">close_connection (EventMachine::Connection)</a><br />
|
29
|
+
<a href="classes/EventMachine/Connection.html#M000024">close_connection (EventMachine::Connection)</a><br />
|
30
|
+
<a href="classes/EventMachine/Connection.html#M000032">close_connection_after_writing (EventMachine::Connection)</a><br />
|
31
|
+
<a href="classes/EventMachine/Connection.html#M000025">close_connection_after_writing (EventMachine::Connection)</a><br />
|
32
|
+
<a href="classes/EventMachine/Connections.html#M000013">connect (EventMachine::Connections)</a><br />
|
33
|
+
<a href="classes/EventMachine.html#M000006">connect (EventMachine)</a><br />
|
34
|
+
<a href="classes/EventMachine.html#M000010">connect (EventMachine)</a><br />
|
35
|
+
<a href="classes/EventMachine.html#M000007">connection_callback (EventMachine)</a><br />
|
36
|
+
<a href="classes/EventMachine/Connection.html#M000027">new (EventMachine::Connection)</a><br />
|
37
|
+
<a href="classes/EventMachine/Connections.html#M000012">new (EventMachine::Connections)</a><br />
|
38
|
+
<a href="classes/EventMachine/Connection.html#M000020">new (EventMachine::Connection)</a><br />
|
39
|
+
<a href="classes/Echo.html#M000034">post_init (Echo)</a><br />
|
40
|
+
<a href="classes/EventMachine/Connection.html#M000021">post_init (EventMachine::Connection)</a><br />
|
41
|
+
<a href="classes/Zzz.html#M000001">receive_data (Zzz)</a><br />
|
42
|
+
<a href="classes/Echo.html#M000033">receive_data (Echo)</a><br />
|
43
|
+
<a href="classes/EventMachine/Connections.html#M000016">receive_data (EventMachine::Connections)</a><br />
|
44
|
+
<a href="classes/EventMachine/Connection.html#M000022">receive_data (EventMachine::Connection)</a><br />
|
45
|
+
<a href="classes/EventMachine/Connection.html#M000030">receive_data (EventMachine::Connection)</a><br />
|
46
|
+
<a href="classes/Echo.html#M000035">receive_data (Echo)</a><br />
|
47
|
+
<a href="classes/EventMachine.html#M000009">run (EventMachine)</a><br />
|
48
|
+
<a href="classes/EventMachine.html#M000002">run (EventMachine)</a><br />
|
49
|
+
<a href="classes/EventMachine/Connections.html#M000018">run_timer (EventMachine::Connections)</a><br />
|
50
|
+
<a href="classes/EventMachine/Connection.html#M000029">send_data (EventMachine::Connection)</a><br />
|
51
|
+
<a href="classes/EventMachine/Connection.html#M000026">send_data (EventMachine::Connection)</a><br />
|
52
|
+
<a href="classes/EventMachine.html#M000011">start_server (EventMachine)</a><br />
|
53
|
+
<a href="classes/EventMachine/Connections.html#M000014">start_server (EventMachine::Connections)</a><br />
|
54
|
+
<a href="classes/EventMachine.html#M000005">start_server (EventMachine)</a><br />
|
55
|
+
<a href="classes/EventMachine/Connection.html#M000028">unbind (EventMachine::Connection)</a><br />
|
56
|
+
<a href="classes/Echo.html#M000036">unbind (Echo)</a><br />
|
57
|
+
<a href="classes/EventMachine/Connection.html#M000023">unbind (EventMachine::Connection)</a><br />
|
58
|
+
<a href="classes/EventMachine/Connections.html#M000015">unbind_connection (EventMachine::Connections)</a><br />
|
59
|
+
</div>
|
60
|
+
</div>
|
61
|
+
</body>
|
62
|
+
</html>
|
data/doc/index.html
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
<?xml version="1.0" encoding="iso-8859-1"?>
|
2
|
+
<!DOCTYPE html
|
3
|
+
PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN"
|
4
|
+
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
|
5
|
+
|
6
|
+
<!--
|
7
|
+
|
8
|
+
RDoc Documentation
|
9
|
+
|
10
|
+
-->
|
11
|
+
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
12
|
+
<head>
|
13
|
+
<title>RDoc Documentation</title>
|
14
|
+
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
|
15
|
+
</head>
|
16
|
+
<frameset rows="20%, 80%">
|
17
|
+
<frameset cols="25%,35%,45%">
|
18
|
+
<frame src="fr_file_index.html" title="Files" name="Files" />
|
19
|
+
<frame src="fr_class_index.html" name="Classes" />
|
20
|
+
<frame src="fr_method_index.html" name="Methods" />
|
21
|
+
</frameset>
|
22
|
+
<frame src="files/binder_cpp.html" name="docwin" />
|
23
|
+
</frameset>
|
24
|
+
</html>
|
Binary file
|
data/lib/eventmachine.rb
ADDED
@@ -0,0 +1,631 @@
|
|
1
|
+
# $Id: eventmachine.rb 2281 2006-04-13 05:09:13Z francis $
|
2
|
+
#
|
3
|
+
# Author:: blackhedd (gmail address: garbagecat20).
|
4
|
+
# Date:: 8 Apr 2006
|
5
|
+
#
|
6
|
+
# Copyright (C) 2006 by Francis Cianfrocca. All Rights Reserved.
|
7
|
+
#
|
8
|
+
# This program is made available under the terms of the GPL version 2.
|
9
|
+
#
|
10
|
+
# See EventMachine and EventMachine::Connection for documentation and
|
11
|
+
# usage examples.
|
12
|
+
#
|
13
|
+
|
14
|
+
require 'libeventmachine'
|
15
|
+
|
16
|
+
# == Introduction
|
17
|
+
# EventMachine provides a fast, lightweight framework for implementing
|
18
|
+
# Ruby programs that can use the network to communicate with other
|
19
|
+
# processes. Using EventMachine, Ruby programmers can easily connect
|
20
|
+
# to remote servers and act as servers themselves. EventMachine does not
|
21
|
+
# supplant the Ruby IP libraries. It does provide an alternate technique
|
22
|
+
# for those applications requiring better performance, scalability,
|
23
|
+
# and discipline over the behavior of network sockets, than is easily
|
24
|
+
# obtainable using the built-in libraries, especially in applications
|
25
|
+
# which are structurally well-suited for the event-driven programming model.
|
26
|
+
#
|
27
|
+
# EventMachine provides a perpetual event-loop which your programs can
|
28
|
+
# start and stop. Within the event loop, TCP network connections are
|
29
|
+
# initiated and accepted, based on EventMachine methods called by your
|
30
|
+
# program. You also define callback methods which are called by EventMachine
|
31
|
+
# when events of interest occur within the event-loop.
|
32
|
+
#
|
33
|
+
# User programs will be called back when the following events occur:
|
34
|
+
# * When the event loop accepts network connections from remote peers
|
35
|
+
# * When data is received from network connections
|
36
|
+
# * When connections are closed, either by the local or the remote side
|
37
|
+
# * When user-defined timers expire
|
38
|
+
#
|
39
|
+
# == Usage example
|
40
|
+
#
|
41
|
+
# Here's a fully-functional echo server implemented in EventMachine:
|
42
|
+
#
|
43
|
+
# require 'rubygems'
|
44
|
+
# require_gem 'eventmachine'
|
45
|
+
#
|
46
|
+
# module EchoServer
|
47
|
+
# def receive_data data
|
48
|
+
# send_data ">>>you sent: #{data}"
|
49
|
+
# close_connection if data =~ /quit/i
|
50
|
+
# end
|
51
|
+
# end
|
52
|
+
#
|
53
|
+
# EventMachine::run {
|
54
|
+
# EventMachine::start_server "192.168.0.100", 8081, EchoServer
|
55
|
+
# }
|
56
|
+
#
|
57
|
+
# What's going on here? Well, we have defined the module EchoServer to
|
58
|
+
# implement the semantics of the echo protocol (more about that shortly).
|
59
|
+
# The last three lines invoke the event-machine itself, which runs forever
|
60
|
+
# unless one of your callbacks terminates it. The block that you supply
|
61
|
+
# to EventMachine::run contains code that runs immediately after the event
|
62
|
+
# machine is initialized and before it starts looping. This is the place
|
63
|
+
# to open up a TCP server by specifying the address and port it will listen
|
64
|
+
# on, together with the module that will process the data.
|
65
|
+
#
|
66
|
+
# Our EchoServer is extremely simple as the echo protocol doesn't require
|
67
|
+
# much work. Basically you want to send back to the remote peer whatever
|
68
|
+
# data it sends you. We'll dress it up with a little extra text to make it
|
69
|
+
# interesting. Also, we'll close the connection in case the received data
|
70
|
+
# contains the word "quit."
|
71
|
+
#
|
72
|
+
# So what about this module EchoServer? Well, whenever a network connection
|
73
|
+
# (either a client or a server) starts up, EventMachine instantiates an anonymous
|
74
|
+
# class, that your module has been mixed into. Exactly one of these class
|
75
|
+
# instances is created for each connection. Whenever an event occurs on a
|
76
|
+
# given connection, its corresponding object automatically calls specific
|
77
|
+
# instance methods which your module may redefine. The code in your module
|
78
|
+
# always runs in the context of a class instance, so you can create instance
|
79
|
+
# variables as you wish and they will be carried over to other callbacks
|
80
|
+
# made on that same connection.
|
81
|
+
#
|
82
|
+
# Looking back up at EchoServer, you can see that we've defined the method
|
83
|
+
# receive_data which (big surprise) is called whenever data has been received
|
84
|
+
# from the remote end of the connection. Very simple. We get the data
|
85
|
+
# (a String object) and can do whatever we wish with it. In this case,
|
86
|
+
# we use the method send_data to return the received data to the caller,
|
87
|
+
# with some extra text added in. And if the user sends the word "quit,"
|
88
|
+
# we'll close the connection with (naturally) close_connection.
|
89
|
+
# (Notice that closing the connection doesn't terminate the processing loop,
|
90
|
+
# or change the fact that your echo server is still accepting connections!)
|
91
|
+
#
|
92
|
+
#
|
93
|
+
# == Questions and Futures
|
94
|
+
# Encryption: EventMachine needs the capability to run SSL/TLS on any
|
95
|
+
# of its clients and servers. Coming soon.
|
96
|
+
#
|
97
|
+
# <tt>epoll(4):</tt> EventMachine currently is based on the <tt>select(2)</tt>
|
98
|
+
# system call in order to be compatible with the widest variety of platforms,
|
99
|
+
# but it would be interesting to re-base it on <tt>epoll(4).</tt>
|
100
|
+
# While requiring a Linux 2.6 kernel, this might possibly give much better
|
101
|
+
# performance and scalability. EventMachine's C++ antecedents already work
|
102
|
+
# with <tt>kqueue</tt> from the BSD world, but it's not yet clear that this
|
103
|
+
# is worth doing. Depends on how many people ask for it.
|
104
|
+
#
|
105
|
+
# Would it be useful for EventMachine to incorporate the Observer pattern
|
106
|
+
# and make use of the corresponding Ruby <tt>observer</tt> package?
|
107
|
+
# Interesting thought.
|
108
|
+
#
|
109
|
+
#
|
110
|
+
module EventMachine
|
111
|
+
|
112
|
+
|
113
|
+
# EventMachine::run initializes and runs an event loop.
|
114
|
+
# This method only returns if user-callback code calls stop_event_loop.
|
115
|
+
# Use the supplied block to define your clients and servers.
|
116
|
+
# The block is called by EventMachine::run immediately after initializing
|
117
|
+
# its internal event loop but <i>before</i> running the loop.
|
118
|
+
# Therefore this block is the right place to call start_server if you
|
119
|
+
# want to accept connections from remote clients.
|
120
|
+
#
|
121
|
+
# For programs that are structured as servers, it's usually appropriate
|
122
|
+
# to start an event loop by calling EventMachine::run, and let it
|
123
|
+
# run forever. It's also possible to use EventMachine::run to make a single
|
124
|
+
# client-connection to a remote server, process the data flow from that
|
125
|
+
# single connection, and then call stop_event_loop to force EventMachine::run
|
126
|
+
# to return. Your program will then continue from the point immediately
|
127
|
+
# following the call to EventMachine::run.
|
128
|
+
#
|
129
|
+
# You can of course do both client and servers simultaneously in the same program.
|
130
|
+
# One of the strengths of the event-driven programming model is that the
|
131
|
+
# handling of network events on many different connections will be interleaved,
|
132
|
+
# and scheduled according to the actual events themselves. This maximizes
|
133
|
+
# efficiency.
|
134
|
+
#
|
135
|
+
# === Server usage example
|
136
|
+
#
|
137
|
+
# See the text at the top of this file for an example of an echo server.
|
138
|
+
#
|
139
|
+
# === Client usage example
|
140
|
+
#
|
141
|
+
# See the description of stop_event_loop for an extremely simple client example.
|
142
|
+
#
|
143
|
+
|
144
|
+
def EventMachine::run &block
|
145
|
+
@conns = {}
|
146
|
+
@acceptors = {}
|
147
|
+
@timers = {}
|
148
|
+
initialize_event_machine
|
149
|
+
block and add_timer 0, block
|
150
|
+
run_machine
|
151
|
+
release_machine
|
152
|
+
end
|
153
|
+
|
154
|
+
# EventMachine#add_timer adds a one-shot timer to the event loop.
|
155
|
+
# Call it with one or two parameters. The first parameters is a delay-time
|
156
|
+
# expressed in <i>seconds</i> (not milliseconds). The second parameter, if
|
157
|
+
# present, must be a proc object. If a proc object is not given, then you
|
158
|
+
# can also simply pass a block to the method call.
|
159
|
+
#
|
160
|
+
# EventMachine#add_timer may be called from the block passed to EventMachine#run
|
161
|
+
# or from any callback method. It schedules execution of the proc or block
|
162
|
+
# passed to add_timer, after the passage of an interval of time equal to
|
163
|
+
# <i>at least</i> the number of seconds specified in the first parameter to
|
164
|
+
# the call.
|
165
|
+
#
|
166
|
+
# EventMachine#add_timer is a <i>non-blocking</i> call. Callbacks can and will
|
167
|
+
# be called during the interval of time that the timer is in effect.
|
168
|
+
# There is no built-in limit to the number of timers that can be outstanding at
|
169
|
+
# any given time.
|
170
|
+
#
|
171
|
+
# === Usage example
|
172
|
+
#
|
173
|
+
# This example shows how easy timers are to use. Observe that two timers are
|
174
|
+
# initiated simultaneously. Also, notice that the event loop will continue
|
175
|
+
# to run even after the second timer event is processed, since there was
|
176
|
+
# no call to EventMachine#stop_event_loop. There will be no activity, of
|
177
|
+
# course, since no network clients or servers are defined. Stop the program
|
178
|
+
# with Ctrl-C.
|
179
|
+
#
|
180
|
+
# require 'rubygems'
|
181
|
+
# require_gem 'eventmachine'
|
182
|
+
#
|
183
|
+
# EventMachine::run {
|
184
|
+
# puts "Starting the run now: #{Time.now}"
|
185
|
+
# EventMachine::add_timer 5, proc { puts "Executing timer event: #{Time.now}" }
|
186
|
+
# EventMachine::add_timer( 10 ) { puts "Executing timer event: #{Time.now}" }
|
187
|
+
# }
|
188
|
+
#
|
189
|
+
#
|
190
|
+
def EventMachine::add_timer *args, &block
|
191
|
+
interval = args.shift
|
192
|
+
code = args.shift || block
|
193
|
+
if code
|
194
|
+
# check too many timers!
|
195
|
+
s = add_oneshot_timer interval
|
196
|
+
@timers[s] = code
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
# EventMachine#add_periodic_timer adds a periodic timer to the event loop.
|
201
|
+
# It takes the same parameters as the one-shot timer method, EventMachine#add_timer.
|
202
|
+
# This method schedules execution of the given block repeatedly, at intervals
|
203
|
+
# of time <i>at least</i> as great as the number of seconds given in the first
|
204
|
+
# parameter to the call.
|
205
|
+
#
|
206
|
+
# === Usage example
|
207
|
+
#
|
208
|
+
# The following sample program will write a dollar-sign to stderr every five seconds.
|
209
|
+
# (Of course if the program defined network clients and/or servers, they would
|
210
|
+
# be doing their work while the periodic timer is counting off.)
|
211
|
+
#
|
212
|
+
# EventMachine::run {
|
213
|
+
# EventMachine::add_periodic_timer( 5 ) { $stderr.write "$" }
|
214
|
+
# }
|
215
|
+
#
|
216
|
+
def EventMachine::add_periodic_timer *args, &block
|
217
|
+
interval = args.shift
|
218
|
+
code = args.shift || block
|
219
|
+
if code
|
220
|
+
block_1 = proc {
|
221
|
+
code.call
|
222
|
+
EventMachine::add_periodic_timer interval, code
|
223
|
+
}
|
224
|
+
add_timer interval, block_1
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
|
229
|
+
# stop_event_loop may called from within a callback method
|
230
|
+
# while EventMachine's processing loop is running.
|
231
|
+
# It causes the processing loop to stop executing, which
|
232
|
+
# will cause all open connections and accepting servers
|
233
|
+
# to be run down and closed. <i>Callbacks for connection-termination
|
234
|
+
# will be called</i> as part of the processing of stop_event_loop.
|
235
|
+
# (There currently is no option to panic-stop the loop without
|
236
|
+
# closing connections.) When all of this processing is complete,
|
237
|
+
# the call to EventMachine::run which started the processing loop
|
238
|
+
# will return and program flow will resume from the statement
|
239
|
+
# following EventMachine::run call.
|
240
|
+
#
|
241
|
+
# === Usage example
|
242
|
+
#
|
243
|
+
# require 'rubygems'
|
244
|
+
# require_gem 'eventmachine'
|
245
|
+
#
|
246
|
+
# module Redmond
|
247
|
+
#
|
248
|
+
# def post_init
|
249
|
+
# puts "We're sending a dumb HTTP request to the remote peer."
|
250
|
+
# send_data "GET / HTTP/1.1\r\nHost: www.microsoft.com\r\n\r\n"
|
251
|
+
# end
|
252
|
+
#
|
253
|
+
# def receive_data data
|
254
|
+
# puts "We received #{data.length} bytes from the remote peer."
|
255
|
+
# puts "We're going to stop the event loop now."
|
256
|
+
# EventMachine::stop_event_loop
|
257
|
+
# end
|
258
|
+
#
|
259
|
+
# def unbind
|
260
|
+
# puts "A connection has terminated."
|
261
|
+
# end
|
262
|
+
#
|
263
|
+
# end
|
264
|
+
#
|
265
|
+
# puts "We're starting the event loop now."
|
266
|
+
# EventMachine::run {
|
267
|
+
# EventMachine::connect "www.microsoft.com", 80, Redmond
|
268
|
+
# }
|
269
|
+
# puts "The event loop has stopped."
|
270
|
+
#
|
271
|
+
# This program will produce approximately the following output:
|
272
|
+
#
|
273
|
+
# We're starting the event loop now.
|
274
|
+
# We're sending a dumb HTTP request to the remote peer.
|
275
|
+
# We received 1440 bytes from the remote peer.
|
276
|
+
# We're going to stop the event loop now.
|
277
|
+
# A connection has terminated.
|
278
|
+
# The event loop has stopped.
|
279
|
+
#
|
280
|
+
#
|
281
|
+
def EventMachine::stop_event_loop
|
282
|
+
EventMachine::stop
|
283
|
+
end
|
284
|
+
|
285
|
+
# EventMachine::start_server initiates a TCP server (socket
|
286
|
+
# acceptor) on the specified IP address and port.
|
287
|
+
# The IP address must be valid on the machine where the program
|
288
|
+
# runs, and the process must be privileged enough to listen
|
289
|
+
# on the specified port (on Unix-like systems, superuser privileges
|
290
|
+
# are usually required to listen on any port lower than 1024).
|
291
|
+
# Only one listener may be running on any given address/port
|
292
|
+
# combination. start_server will fail if the given address and port
|
293
|
+
# are already listening on the machine, either because of a prior call
|
294
|
+
# to start_server or some unrelated process running on the machine.
|
295
|
+
# If start_server succeeds, the new network listener becomes active
|
296
|
+
# immediately and starts accepting connections from remote peers,
|
297
|
+
# and these connections generate callback events that are processed
|
298
|
+
# by the code specified in the handler parameter to start_server.
|
299
|
+
#
|
300
|
+
# The optional handler which is passed to start_server is the key
|
301
|
+
# to EventMachine's ability to handle particular network protocols.
|
302
|
+
# The handler parameter passed to start_server must be a Ruby Module
|
303
|
+
# that you must define. When the network server that is started by
|
304
|
+
# start_server accepts a new connection, it instantiates a new
|
305
|
+
# object of an anonymous class that is inherited from EventMachine::Connection,
|
306
|
+
# <i>into which the methods from your handler have been mixed.</i>
|
307
|
+
# Your handler module may redefine any of the methods in EventMachine::Connection
|
308
|
+
# in order to implement the specific behavior of the network protocol.
|
309
|
+
#
|
310
|
+
# Callbacks invoked in response to network events <i>always</i> take place
|
311
|
+
# within the execution context of the object derived from EventMachine::Connection
|
312
|
+
# extended by your handler module. There is one object per connection, and
|
313
|
+
# all of the callbacks invoked for a particular connection take the form
|
314
|
+
# of instance methods called against the corresponding EventMachine::Connection
|
315
|
+
# object. Therefore, you are free to define whatever instance variables you
|
316
|
+
# wish, in order to contain the per-connection state required by the network protocol you are
|
317
|
+
# implementing.
|
318
|
+
#
|
319
|
+
# start_server is often called inside the block passed to EventMachine::run,
|
320
|
+
# but it can be called from any EventMachine callback. start_server will fail
|
321
|
+
# unless the EventMachine event loop is currently running (which is why
|
322
|
+
# it's often called in the block suppled to EventMachine::run).
|
323
|
+
#
|
324
|
+
# You may call start_server any number of times to start up network
|
325
|
+
# listeners on different address/port combinations. The servers will
|
326
|
+
# all run simultaneously. More interestingly, each individual call to start_server
|
327
|
+
# can specify a different handler module and thus implement a different
|
328
|
+
# network protocol from all the others.
|
329
|
+
#
|
330
|
+
# === Usage example
|
331
|
+
# Here is an example of a server that counts lines of input from the remote
|
332
|
+
# peer and sends back the total number of lines received, after each line.
|
333
|
+
# Try the example with more than one client connection opened via telnet,
|
334
|
+
# and you will see that the line count increments independently on each
|
335
|
+
# of the client connections. Also very important to note, is that the
|
336
|
+
# handler for the receive_data function, which our handler redefines, may
|
337
|
+
# not assume that the data it receives observes any kind of message boundaries.
|
338
|
+
# Also, to use this example, be sure to change the server and port parameters
|
339
|
+
# to the start_server call to values appropriate for your environment.
|
340
|
+
#
|
341
|
+
# require 'rubygems'
|
342
|
+
# require_gem 'eventmachine'
|
343
|
+
#
|
344
|
+
# module LineCounter
|
345
|
+
#
|
346
|
+
# MaxLinesPerConnection = 10
|
347
|
+
#
|
348
|
+
# def post_init
|
349
|
+
# puts "Received a new connection"
|
350
|
+
# @data_received = ""
|
351
|
+
# @line_count = 0
|
352
|
+
# end
|
353
|
+
#
|
354
|
+
# def receive_data data
|
355
|
+
# @data_received << data
|
356
|
+
# while @data_received.slice!( /^[^\n]*[\n]/m )
|
357
|
+
# @line_count += 1
|
358
|
+
# send_data "received #{@line_count} lines so far\r\n"
|
359
|
+
# @line_count == MaxLinesPerConnection and close_connection_after_writing
|
360
|
+
# end
|
361
|
+
# end
|
362
|
+
#
|
363
|
+
# end # module LineCounter
|
364
|
+
#
|
365
|
+
# EventMachine::run {
|
366
|
+
# host,port = "192.168.0.100", 8090
|
367
|
+
# EventMachine::start_server host, port, LineCounter
|
368
|
+
# puts "Now accepting connections on address #{host}, port #{port}..."
|
369
|
+
# EventMachine::add_periodic_timer( 10 ) { $stderr.write "*" }
|
370
|
+
# }
|
371
|
+
#
|
372
|
+
#
|
373
|
+
def EventMachine::start_server server, port, handler=nil
|
374
|
+
s = start_tcp_server server, port
|
375
|
+
@acceptors[s] = Class.new( Connection ) {
|
376
|
+
handler and include handler
|
377
|
+
}
|
378
|
+
end
|
379
|
+
|
380
|
+
# EventMachine#connect initiates a TCP connection to a remote
|
381
|
+
# server and sets up event-handling for the connection.
|
382
|
+
# You can call EventMachine#connect in the block supplied
|
383
|
+
# to EventMachine#run or in any callback method.
|
384
|
+
#
|
385
|
+
# EventMachine#connect takes the IP address (or hostname) and
|
386
|
+
# port of the remote server you want to connect to.
|
387
|
+
# It also takes an optional handler Module which you must define, that
|
388
|
+
# contains the callbacks that will be invoked by the event loop
|
389
|
+
# on behalf of the connection.
|
390
|
+
#
|
391
|
+
# See the description of EventMachine#start_server for a discussion
|
392
|
+
# of the handler Module. All of the details given in that description
|
393
|
+
# apply for connections created with EventMachine#connect.
|
394
|
+
#
|
395
|
+
# === Usage Example
|
396
|
+
#
|
397
|
+
# Here's a program which connects to a web server, sends a naive
|
398
|
+
# request, parses the HTTP header of the response, and then
|
399
|
+
# (antisocially) ends the event loop, which automatically drops the connection
|
400
|
+
# (and incidentally calls the connection's unbind method).
|
401
|
+
#
|
402
|
+
# require 'rubygems'
|
403
|
+
# require_gem 'eventmachine'
|
404
|
+
#
|
405
|
+
# module DumbHttpClient
|
406
|
+
#
|
407
|
+
# def post_init
|
408
|
+
# send_data "GET / HTTP/1.1\r\nHost: _\r\n\r\n"
|
409
|
+
# @data = ""
|
410
|
+
# end
|
411
|
+
#
|
412
|
+
# def receive_data data
|
413
|
+
# @data << data
|
414
|
+
# if @data =~ /[\n][\r]*[\n]/m
|
415
|
+
# puts "RECEIVED HTTP HEADER:"
|
416
|
+
# $`.each {|line| puts ">>> #{line}" }
|
417
|
+
#
|
418
|
+
# puts "Now we'll terminate the loop, which will also close the connection"
|
419
|
+
# EventMachine::stop_event_loop
|
420
|
+
# end
|
421
|
+
# end
|
422
|
+
#
|
423
|
+
# def unbind
|
424
|
+
# puts "A connection has terminated"
|
425
|
+
# end
|
426
|
+
#
|
427
|
+
# end # DumbHttpClient
|
428
|
+
#
|
429
|
+
#
|
430
|
+
# EventMachine::run {
|
431
|
+
# EventMachine::connect "www.bayshorenetworks.com", 80, DumbHttpClient
|
432
|
+
# }
|
433
|
+
# puts "The event loop has ended"
|
434
|
+
#
|
435
|
+
#--
|
436
|
+
# EventMachine::connect initiates a TCP connection to a remote
|
437
|
+
# server and sets up event-handling for the connection.
|
438
|
+
# It internally creates an object that should not be handled
|
439
|
+
# by the caller. HOWEVER, it's often convenient to get the
|
440
|
+
# object to set up interfacing to other objects in the system.
|
441
|
+
# We return the newly-created anonymous-class object to the caller.
|
442
|
+
# It's expected that a considerable amount of code will depend
|
443
|
+
# on this behavior, so don't change it.
|
444
|
+
#
|
445
|
+
def EventMachine::connect server, port, handler=nil
|
446
|
+
s = connect_server server, port
|
447
|
+
klass = Class.new( Connection ) {
|
448
|
+
handler and include handler
|
449
|
+
}
|
450
|
+
c = klass.new s
|
451
|
+
@conns[s] = c
|
452
|
+
end
|
453
|
+
|
454
|
+
|
455
|
+
private
|
456
|
+
def EventMachine::event_callback conn_binding, opcode, data
|
457
|
+
case opcode
|
458
|
+
when ConnectionData
|
459
|
+
c = @conns[conn_binding] or raise ConnectionNotBound
|
460
|
+
c.receive_data data
|
461
|
+
when ConnectionUnbound
|
462
|
+
if c = @conns.delete( conn_binding )
|
463
|
+
c.unbind
|
464
|
+
elsif c = @acceptors.delete( conn_binding )
|
465
|
+
# no-op
|
466
|
+
else
|
467
|
+
raise ConnectionNotBound
|
468
|
+
end
|
469
|
+
when ConnectionAccepted
|
470
|
+
accep = @acceptors[conn_binding] or raise NoHandlerForAcceptedConnection
|
471
|
+
c = accep.new data
|
472
|
+
@conns[data] = c
|
473
|
+
when TimerFired
|
474
|
+
t = @timers.delete( data ) or raise UnknownTimerFired
|
475
|
+
t.call
|
476
|
+
end
|
477
|
+
end
|
478
|
+
|
479
|
+
|
480
|
+
|
481
|
+
# EventMachine::Connection is a class that is instantiated
|
482
|
+
# by EventMachine's processing loop whenever a new connection
|
483
|
+
# is created. (New connections can be either initiated locally
|
484
|
+
# to a remote server or accepted locally from a remote client.)
|
485
|
+
# When a Connection object is instantiated, it <i>mixes in</i>
|
486
|
+
# the functionality contained in the user-defined module
|
487
|
+
# specified in calls to EventMachine#connect or EventMachine#start_server.
|
488
|
+
# User-defined handler modules may redefine any or all of the standard
|
489
|
+
# methods defined here, as well as add arbitrary additional code
|
490
|
+
# that will also be mixed in.
|
491
|
+
#
|
492
|
+
# EventMachine manages one object inherited from EventMachine::Connection
|
493
|
+
# (and containing the mixed-in user code) for every network connection
|
494
|
+
# that is active at any given time.
|
495
|
+
# The event loop will automatically call methods on EventMachine::Connection
|
496
|
+
# objects whenever specific events occur on the corresponding connections,
|
497
|
+
# as described below.
|
498
|
+
#
|
499
|
+
# This class is never instantiated by user code, and does not publish an
|
500
|
+
# initialize method. The instance methods of EventMachine::Connection
|
501
|
+
# which may be called by the event loop are: post_init, receive_data,
|
502
|
+
# and unbind. All of the other instance methods defined here are called
|
503
|
+
# only by user code.
|
504
|
+
#
|
505
|
+
class Connection
|
506
|
+
|
507
|
+
def initialize sig #:nodoc:
|
508
|
+
@signature = sig
|
509
|
+
post_init
|
510
|
+
end
|
511
|
+
|
512
|
+
# EventMachine::Connection#post_init is called by the event loop
|
513
|
+
# immediately after the network connection has been established,
|
514
|
+
# and before resumption of the network loop.
|
515
|
+
# This method is generally not called by user code, but is called automatically
|
516
|
+
# by the event loop. The base-class implementation is a no-op.
|
517
|
+
# This is a very good place to initialize instance variables that will
|
518
|
+
# be used throughout the lifetime of the network connection.
|
519
|
+
#
|
520
|
+
def post_init
|
521
|
+
end
|
522
|
+
|
523
|
+
# EventMachine::Connection#receive_data is called by the event loop
|
524
|
+
# whenever data has been received by the network connection.
|
525
|
+
# It is never called by user code.
|
526
|
+
# receive_data is called with a single parameter, a String containing
|
527
|
+
# the network protocol data, which may of course be binary. You will
|
528
|
+
# generally redefine this method to perform your own processing of the incoming data.
|
529
|
+
#
|
530
|
+
# Here's a key point which is essential to understanding the event-driven
|
531
|
+
# programming model: <i>EventMachine knows absolutely nothing about the protocol
|
532
|
+
# which your code implements.</i> You must not make any assumptions about
|
533
|
+
# the size of the incoming data packets, or about their alignment on any
|
534
|
+
# particular intra-message or PDU boundaries (such as line breaks).
|
535
|
+
# receive_data can and will send you arbitrary chunks of data, with the
|
536
|
+
# only guarantee being that the data is presented to your code in the order
|
537
|
+
# it was collected from the network. Don't even assume that the chunks of
|
538
|
+
# data will correspond to network packets, as EventMachine can and will coalesce
|
539
|
+
# several incoming packets into one, to improve performance. The implication for your
|
540
|
+
# code is that you generally will need to implement some kind of a state machine
|
541
|
+
# in your redefined implementation of receive_data. For a better understanding
|
542
|
+
# of this, read through the examples of specific protocol handlers given
|
543
|
+
# elsewhere in this package. (STUB, WE MUST ADD THESE!)
|
544
|
+
#
|
545
|
+
# The base-class implementation of receive_data (which will be invoked if
|
546
|
+
# you don't redefine it) simply prints the size of each incoming data packet
|
547
|
+
# to stdout.
|
548
|
+
#
|
549
|
+
def receive_data data
|
550
|
+
puts "............>>>#{data.length}"
|
551
|
+
end
|
552
|
+
|
553
|
+
# EventMachine::Connection#unbind is called by the framework whenever a connection
|
554
|
+
# (either a server or client connection) is closed. The close can occur because
|
555
|
+
# your code intentionally closes it (see close_connection and close_connection_after_writing),
|
556
|
+
# because the remote peer closed the connection, or because of a network error.
|
557
|
+
# You may not assume that the network connection is still open and able to send or
|
558
|
+
# receive data when the callback to unbind is made. This is intended only to give
|
559
|
+
# you a chance to clean up associations your code may have made to the connection
|
560
|
+
# object while it was open.
|
561
|
+
#
|
562
|
+
def unbind
|
563
|
+
end
|
564
|
+
|
565
|
+
# EventMachine::Connection#close_connection is called only by user code, and never
|
566
|
+
# by the event loop. You may call this method against a connection object in any
|
567
|
+
# callback handler, whether or not the callback was made against the connection
|
568
|
+
# you want to close. close_connection <i>schedules</i> the connection to be closed
|
569
|
+
# at the next available opportunity within the event loop. You may not assume that
|
570
|
+
# the connection is closed when close_connection returns. In particular, the framework
|
571
|
+
# will callback the unbind method for the particular connection at a point shortly
|
572
|
+
# after you call close_connection. You may assume that the unbind callback will
|
573
|
+
# take place sometime after your call to close_connection completes. In other words,
|
574
|
+
# the unbind callback will not re-enter your code "inside" of your call to close_connection.
|
575
|
+
# However, it's not guaranteed that a future version of EventMachine will not change
|
576
|
+
# this behavior.
|
577
|
+
#
|
578
|
+
# close_connection will <i>silently discard</i> any outbound data which you have
|
579
|
+
# sent to the connection using EventMachine::Connection#send_data but which has not
|
580
|
+
# yet been sent across the network. If you want to avoid this behavior, use
|
581
|
+
# EventMachine::Connection#close_connection_after_writing.
|
582
|
+
#
|
583
|
+
def close_connection after_writing = false
|
584
|
+
EventMachine::close_connection @signature, after_writing
|
585
|
+
end
|
586
|
+
|
587
|
+
# EventMachine::Connection#close_connection_after_writing is a variant of close_connection.
|
588
|
+
# All of the descriptive comments given for close_connection also apply to
|
589
|
+
# close_connection_after_writing, <i>with one exception:</i> If the connection has
|
590
|
+
# outbound data sent using send_dat but which has not yet been sent across the network,
|
591
|
+
# close_connection_after_writing will schedule the connection to be closed <i>after</i>
|
592
|
+
# all of the outbound data has been safely written to the remote peer.
|
593
|
+
#
|
594
|
+
# Depending on the amount of outgoing data and the speed of the network,
|
595
|
+
# considerable time may elapse between your call to close_connection_after_writing
|
596
|
+
# and the actual closing of the socket (at which time the unbind callback will be called
|
597
|
+
# by the event loop). During this time, you <i>may not</i> call send_data to transmit
|
598
|
+
# additional data (that is, the connection is closed for further writes). In very
|
599
|
+
# rare cases, you may experience a receive_data callback after your call to close_connection_after_writing,
|
600
|
+
# depending on whether incoming data was in the process of being received on the connection
|
601
|
+
# at the moment when you called close_connection_after_writing. Your protocol handler must
|
602
|
+
# be prepared to properly deal with such data (probably by ignoring it).
|
603
|
+
#
|
604
|
+
def close_connection_after_writing
|
605
|
+
close_connection true
|
606
|
+
end
|
607
|
+
|
608
|
+
# EventMachine::Connection#send_data is only called by user code, never by
|
609
|
+
# the event loop. You call this method to send data to the remote end of the
|
610
|
+
# network connection. send_data is called with a single String argument, which
|
611
|
+
# may of course contain binary data. You can call send_data any number of times.
|
612
|
+
# send_data is an instance method of an object derived from EventMachine::Connection
|
613
|
+
# and containing your mixed-in handler code), so if you call it without qualification
|
614
|
+
# within a callback function, the data will be sent to the same network connection
|
615
|
+
# that generated the callback. Calling self.send_data is exactly equivalent.
|
616
|
+
#
|
617
|
+
# You can also call send_data to write to a connection <i>other than the one
|
618
|
+
# whose callback you are calling send_data from.</i> This is done by recording
|
619
|
+
# the value of the connection in any callback function (the value self), in any
|
620
|
+
# variable visible to other callback invocations on the same or different
|
621
|
+
# connection objects. (Need an example to make that clear.)
|
622
|
+
#
|
623
|
+
def send_data data
|
624
|
+
EventMachine::send_data @signature, data, data.length
|
625
|
+
end
|
626
|
+
|
627
|
+
end
|
628
|
+
|
629
|
+
|
630
|
+
end # module EventMachine
|
631
|
+
|