net-reactor 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/lib/net/reactor.rb +135 -0
- metadata +47 -0
data/lib/net/reactor.rb
ADDED
@@ -0,0 +1,135 @@
|
|
1
|
+
# License: GPLv2
|
2
|
+
# Author: Tassilo Schweyer<welterde@arcor.de>
|
3
|
+
# Usage:
|
4
|
+
# require 'net/reactor'
|
5
|
+
# class Handler
|
6
|
+
# def initialize connection
|
7
|
+
# @connection = connection
|
8
|
+
# ...
|
9
|
+
# end
|
10
|
+
# def readEvent lines
|
11
|
+
# ...
|
12
|
+
# @connection.write lines[0]
|
13
|
+
# ...
|
14
|
+
# end
|
15
|
+
# end
|
16
|
+
# server = Net::Reactor::Server.new(4000, Handler)
|
17
|
+
|
18
|
+
begin
|
19
|
+
require 'rubygems'
|
20
|
+
rescue LoadError
|
21
|
+
# ignore
|
22
|
+
end
|
23
|
+
require 'io/reactor'
|
24
|
+
require 'socket'
|
25
|
+
|
26
|
+
module Net
|
27
|
+
module Reactor
|
28
|
+
class Server
|
29
|
+
def initialize(port, handler, host='0.0.0.0', interval=0.20)
|
30
|
+
@socket = TCPServer::new(host, port)
|
31
|
+
@handler = handler
|
32
|
+
@port = port
|
33
|
+
@pollInterval = interval
|
34
|
+
@reactor = IO::Reactor.new
|
35
|
+
@doShutdown = false
|
36
|
+
@connections = []
|
37
|
+
|
38
|
+
@reactor.register @socket, :read, &method(:handlePollEvent)
|
39
|
+
end
|
40
|
+
|
41
|
+
def handlePollEvent(socket, event)
|
42
|
+
case event
|
43
|
+
when :error
|
44
|
+
# TODO: log this error
|
45
|
+
shutdown
|
46
|
+
when :read
|
47
|
+
handleAccept(socket)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def handleAccept socket
|
52
|
+
sock = socket.accept
|
53
|
+
hand = Connection.new(sock, @handler, @reactor)
|
54
|
+
@reactor.register sock, :read, &hand.method(:handleIOEvent)
|
55
|
+
@connections << hand
|
56
|
+
end
|
57
|
+
|
58
|
+
def run
|
59
|
+
until @doShutdown
|
60
|
+
@reactor.poll(@pollInterval)
|
61
|
+
end
|
62
|
+
@connections.each do |connection|
|
63
|
+
@reactor.unregister connection.socket
|
64
|
+
connection.disconnected
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def shutdown
|
69
|
+
@doShutdown = true
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
class Connection
|
74
|
+
MTU = 4096
|
75
|
+
CR = "\015"
|
76
|
+
LF = "\012"
|
77
|
+
EOL = CR + LF
|
78
|
+
|
79
|
+
def initialize(socket, handler, reactor)
|
80
|
+
@handler = handler.new self
|
81
|
+
@socket = socket
|
82
|
+
@reactor = reactor
|
83
|
+
|
84
|
+
@write_buffer = ''
|
85
|
+
@read_buffer = ''
|
86
|
+
end
|
87
|
+
|
88
|
+
def handleIOEvent(io, event)
|
89
|
+
case event
|
90
|
+
when :error
|
91
|
+
@handler.disconnected 'socket failed'
|
92
|
+
when :read
|
93
|
+
begin
|
94
|
+
handleRead
|
95
|
+
rescue EOFError
|
96
|
+
@handler.disconnected 'connection closed by remote host'
|
97
|
+
end
|
98
|
+
when :write
|
99
|
+
handleWrite
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def write msg
|
104
|
+
@write_buffer << msg
|
105
|
+
@reactor.enableEvents(@socket, :write)
|
106
|
+
end
|
107
|
+
|
108
|
+
def handleWrite
|
109
|
+
bytes = @socket.syswrite(@write_buffer)
|
110
|
+
@write_buffer[ 0, bytes ] = '' if bytes.nonzero?
|
111
|
+
@reactor.disableEvents(@socket, :write) if @write_buffer.length.zero?
|
112
|
+
end
|
113
|
+
|
114
|
+
def handleRead
|
115
|
+
lines = []
|
116
|
+
@read_buffer << @socket.sysread(MTU)
|
117
|
+
if @read_buffer.index EOL
|
118
|
+
lines = @read_buffer.split EOL
|
119
|
+
else
|
120
|
+
lines = @read_buffer
|
121
|
+
end
|
122
|
+
@read_buffer[0, @read_buffer.length] = ''
|
123
|
+
@handler.readEvent lines
|
124
|
+
end
|
125
|
+
|
126
|
+
#delegate
|
127
|
+
def disconnected
|
128
|
+
@handler.disconnected 'socket closed'
|
129
|
+
end
|
130
|
+
|
131
|
+
attr_reader :socket
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
metadata
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
rubygems_version: 0.9.0
|
3
|
+
specification_version: 1
|
4
|
+
name: net-reactor
|
5
|
+
version: !ruby/object:Gem::Version
|
6
|
+
version: 0.0.1
|
7
|
+
date: 2007-04-05 00:00:00 +02:00
|
8
|
+
summary: An simple async network-engine for plain text
|
9
|
+
require_paths:
|
10
|
+
- lib
|
11
|
+
email:
|
12
|
+
homepage:
|
13
|
+
rubyforge_project:
|
14
|
+
description:
|
15
|
+
autorequire:
|
16
|
+
default_executable:
|
17
|
+
bindir: bin
|
18
|
+
has_rdoc: "true"
|
19
|
+
required_ruby_version: !ruby/object:Gem::Version::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">"
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 0.0.0
|
24
|
+
version:
|
25
|
+
platform: ruby
|
26
|
+
signing_key:
|
27
|
+
cert_chain:
|
28
|
+
post_install_message:
|
29
|
+
authors:
|
30
|
+
- Tassilo Schweyer
|
31
|
+
files:
|
32
|
+
- lib/net
|
33
|
+
- lib/net/reactor.rb
|
34
|
+
test_files: []
|
35
|
+
|
36
|
+
rdoc_options: []
|
37
|
+
|
38
|
+
extra_rdoc_files: []
|
39
|
+
|
40
|
+
executables: []
|
41
|
+
|
42
|
+
extensions: []
|
43
|
+
|
44
|
+
requirements: []
|
45
|
+
|
46
|
+
dependencies: []
|
47
|
+
|