Class: TinyTCPService
- Inherits:
-
Object
- Object
- TinyTCPService
- Defined in:
- lib/tiny_tcp_service.rb
Overview
usage:
s = TinyTCPService.new(
1234,
->(m) { puts m }
)
s.start! # everything runs in background threads
s.stop! # gracefully shutdown the server
TinyTCPService implements a line-based, call and response protocol, where every incoming message must be a newline-terminated (“n”) String, and for every received message the service responds with a newline-terminated String. been set).
If you need more complex objects to be sent over the wire, consider something like JSON.
NOTE: if you’re running a TinyTCPService and a client of your system violates your communication protocol, you should raise an instance of TinyTCPService::BadClient, and the TinyTCPService instance will take care of safely removing the client.
Defined Under Namespace
Classes: BadClient
Instance Method Summary collapse
- #_remove_client!(c) ⇒ Object
-
#add_error_handler(klass, block) ⇒ Object
add the error handler and block for the specified class.
-
#initialize(port) ⇒ TinyTCPService
constructor
A new instance of TinyTCPService.
-
#msg_handler=(h) ⇒ Object
h - some object that responds to #call.
-
#num_clients ⇒ Object
returns the number of connected clients.
-
#remove_error_handler(klass) ⇒ Object
remove the error handler associated with klass.
-
#running? ⇒ Boolean
returns true if the server is running false otherwise.
-
#start! ⇒ Object
starts the server.
-
#stop! ⇒ Object
stops the server gracefully.
Constructor Details
#initialize(port) ⇒ TinyTCPService
Returns a new instance of TinyTCPService.
25 26 27 28 29 30 31 32 33 34 |
# File 'lib/tiny_tcp_service.rb', line 25 def initialize(port) @port = port @server = TCPServer.new(port) @clients = [] @running = false @msg_handler = nil @error_handlers = {} end |
Instance Method Details
#_remove_client!(c) ⇒ Object
64 65 66 67 |
# File 'lib/tiny_tcp_service.rb', line 64 def _remove_client!(c) @clients.delete(c) c.close if c && !c.closed? end |
#add_error_handler(klass, block) ⇒ Object
add the error handler and block for the specified class
you can assume that the local variable name of the error will be ‘e’
50 51 52 |
# File 'lib/tiny_tcp_service.rb', line 50 def add_error_handler(klass, block) @error_handlers[klass] = block end |
#msg_handler=(h) ⇒ Object
h - some object that responds to #call
37 38 39 |
# File 'lib/tiny_tcp_service.rb', line 37 def msg_handler=(h) @msg_handler = h end |
#num_clients ⇒ Object
returns the number of connected clients
60 61 62 |
# File 'lib/tiny_tcp_service.rb', line 60 def num_clients @clients.length end |
#remove_error_handler(klass) ⇒ Object
remove the error handler associated with klass
55 56 57 |
# File 'lib/tiny_tcp_service.rb', line 55 def remove_error_handler(klass) @error_handlers.delete(klass) end |
#running? ⇒ Boolean
returns true if the server is running false otherwise
43 44 45 |
# File 'lib/tiny_tcp_service.rb', line 43 def running? @running end |
#start! ⇒ Object
starts the server
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 |
# File 'lib/tiny_tcp_service.rb', line 70 def start! return if running? @running = true # client accept thread Thread.new do |t| loop do break unless running? @clients << @server.accept end @clients.each{|c| _remove_client!(c) if c && !c.closed? } @server.close end # service thread Thread.new do |t| loop do break unless running? readable, _, errored = IO.select(@clients, nil, @clients, 1) readable&.each do |c| begin c.puts(@msg_handler&.call(c.gets.chomp)) rescue TinyTCPService::BadClient => e _remove_client!(c) rescue => e handler = @error_handlers[e.class] if handler handler.call(e) else stop! raise e end end end errored&.each do |c| _remove_client!(c) end end end end |
#stop! ⇒ Object
stops the server gracefully
116 117 118 |
# File 'lib/tiny_tcp_service.rb', line 116 def stop! @running = false end |