easy_sockets 0.1.0 → 1.0.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6cda3ce2892a6052d57ed242708f762febe57481
4
- data.tar.gz: fa52646d15d1aede1b25c6a612aab869c767d8da
3
+ metadata.gz: f80b06dbbb87b666cb3b6664d405c95e1a1fc27f
4
+ data.tar.gz: 4494590df3d194153ccbe2ecdd530d49fac19df7
5
5
  SHA512:
6
- metadata.gz: 4160e8c1d10c54a8998c4d071de8b9f91215c157925814a36f5d097cf0804db2a1e76d58a5c6bb75117ed747d9735d2b4655873438686160a312b17684745e27
7
- data.tar.gz: 3324c1006ccc13d583dce4d1aa6d037a94e7e8cacadc0d58aaf411ce8a73ceb88b0f642aadb25d1abaa803c9cafd5ced03b71a2d3aa1a97b41294c1ab59b70ac
6
+ metadata.gz: 01bc5222921c85853927282f57c97de241dbb4ff8d7d9c25627974b3f55422030cb88c9ed9d377c3875dca2fbf08aabb7de2ead1a36339e63f46fccbc6961ac9
7
+ data.tar.gz: 19fe1923e0063a4f36faa055ceada93a089d322f2a3dc0aac06cd5f344aa03dc28fac7b91f067acbaae331833ae3484aa0b4c0f8ade9bf3cbb9850e5f3d2d67d
@@ -1,4 +1,6 @@
1
+ ## 1.0.0 (2016-07-08)
2
+ Features:
3
+ - Adding support to udp and unix sockets.
1
4
  ## 0.1.0 (2016-06-28)
2
5
  Features:
3
6
  - EasySockets::TcpSocket now reads and writes in a non blocking way.
4
- - Adding support to unix sockets.
data/README.md CHANGED
@@ -20,7 +20,7 @@
20
20
 
21
21
  ## Description
22
22
 
23
- Over and over I see developers struggling to implement basic sockets with featues available on ruby socket stdlib.
23
+ Over and over I see developers struggling to implement basic sockets with features available on ruby socket stdlib.
24
24
 
25
25
  easy_sockets, takes care of basic details that usually are overlooked by developers when implementing TCP/Unix sockets from scratch.
26
26
 
@@ -191,7 +191,7 @@ Press `Ctrl+c` on the client and server terminal windows to terminate both.
191
191
 
192
192
  Open up a terminal window and type the following to start a Unix server:
193
193
  ```bash
194
- nc -Ul /tmp/test_socket
194
+ nc -Ucl /tmp/test_socket
195
195
  ```
196
196
 
197
197
  On another terminal window, run the following [code](https://github.com/marcosortiz/easy_sockets/blob/master/examples/unix_socket.rb) to start the client:
@@ -263,6 +263,82 @@ Please write the message you want to send and hit ENTER, or type Ctrl+c to quit:
263
263
 
264
264
  Press `Ctrl+c` on the client and server terminal windows to terminate both. Also, type `rm -rf /tmp/test_socket` to remove the socket file.
265
265
 
266
+ ### UDP Sockets
267
+
268
+ Open up a terminal window and type the following to start a TCP server:
269
+ ```bash
270
+ nc -ukcl 2500
271
+ ```
272
+
273
+ On another terminal window, run the following [code](https://github.com/marcosortiz/easy_sockets/blob/master/examples/udp_socket.rb) to start the client:
274
+ ```ruby
275
+ require 'easy_sockets'
276
+
277
+ host = ARGV[0] || '127.0.0.1'
278
+
279
+ port = ARGV[1].to_i
280
+ port = 2500 if port <= 0
281
+
282
+ opts = {
283
+ host: host,
284
+ port: port,
285
+ timeout: 300,
286
+ separator: "\r\n",
287
+ logger: Logger.new(STDOUT),
288
+ }
289
+ s = EasySockets::UdpSocket.new(opts)
290
+ [:INT, :QUIT, :TERM].each do |signal|
291
+ Signal.trap(signal) do
292
+ exit
293
+ end
294
+ end
295
+
296
+ loop do
297
+ puts "Please write the message you want to send and hit ENTER, or type Ctrl+c to quit:"
298
+ msg = gets.chomp
299
+ s.send_msg(msg)
300
+ end
301
+ ```
302
+
303
+ Then typing `sample_request` in the client terminal, you should see:
304
+ ```
305
+ $ bundle exec ruby examples/udp_socket.rb
306
+ Please write the message you want to send and hit ENTER, or type Ctrl+c to quit:
307
+ sample_request
308
+ D, [2016-07-08T10:45:17.935787 #83697] DEBUG -- : Successfully connected to udp://127.0.0.1:2500.
309
+ D, [2016-07-08T10:45:17.935893 #83697] DEBUG -- : Sending "sample_request\r\n"
310
+
311
+ ```
312
+
313
+ And the server terminal window should display:
314
+ ```
315
+ $ nc -ukcl 2500
316
+ sample_request
317
+
318
+ ```
319
+
320
+ Then type `sample_response` on the server terminal window, and you should see:
321
+ ```
322
+ $ nc -ukcl 2500
323
+ sample_request
324
+ sample_response
325
+
326
+ ```
327
+
328
+ And the client window should show:
329
+ ```
330
+ $ bundle exec ruby examples/udp_socket.rb
331
+ Please write the message you want to send and hit ENTER, or type Ctrl+c to quit:
332
+ sample_request
333
+ D, [2016-07-08T10:45:17.935787 #83697] DEBUG -- : Successfully connected to udp://127.0.0.1:2500.
334
+ D, [2016-07-08T10:45:17.935893 #83697] DEBUG -- : Sending "sample_request\r\n"
335
+ D, [2016-07-08T10:45:22.086731 #83697] DEBUG -- : Got "sample_response\r\n"
336
+ Please write the message you want to send and hit ENTER, or type Ctrl+c to quit:
337
+
338
+ ```
339
+
340
+ Press `Ctrl+c` on the client and server terminal windows to terminate both.
341
+
266
342
  ## Development
267
343
 
268
344
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
@@ -12,7 +12,7 @@ opts = {
12
12
  separator: "\r\n",
13
13
  logger: Logger.new(STDOUT),
14
14
  }
15
- s = EasySockets::UnixSocket.new(opts)
15
+ s = EasySockets::TcpSocket.new(opts)
16
16
  [:INT, :QUIT, :TERM].each do |signal|
17
17
  Signal.trap(signal) do
18
18
  exit
@@ -0,0 +1,26 @@
1
+ require 'easy_sockets'
2
+
3
+ host = ARGV[0] || '127.0.0.1'
4
+
5
+ port = ARGV[1].to_i
6
+ port = 2500 if port <= 0
7
+
8
+ opts = {
9
+ host: host,
10
+ port: port,
11
+ timeout: 300,
12
+ separator: "\r\n",
13
+ logger: Logger.new(STDOUT),
14
+ }
15
+ s = EasySockets::UdpSocket.new(opts)
16
+ [:INT, :QUIT, :TERM].each do |signal|
17
+ Signal.trap(signal) do
18
+ exit
19
+ end
20
+ end
21
+
22
+ loop do
23
+ puts "Please write the message you want to send and hit ENTER, or type Ctrl+c to quit:"
24
+ msg = gets.chomp
25
+ s.send_msg(msg)
26
+ end
data/lib/easy_sockets.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  require "easy_sockets/version"
2
2
  require "easy_sockets/tcp/tcp_socket"
3
+ require "easy_sockets/udp/udp_socket"
3
4
  require "easy_sockets/unix/unix_socket"
4
5
 
5
6
  module EasySockets
@@ -16,7 +16,7 @@ module EasySockets
16
16
  def initialize(opts={})
17
17
  super(opts)
18
18
 
19
- @port = opts[:port].to_i || '127.0.0.1'
19
+ @port = opts[:port].to_i
20
20
  @port = DEFAULT_PORT if @port <= 0
21
21
  @host = opts[:host] || DEFAULT_HOST
22
22
  end
@@ -0,0 +1,83 @@
1
+ require 'logger'
2
+ require 'socket'
3
+ require 'easy_sockets/constants'
4
+ require 'easy_sockets/utils/server_utils'
5
+
6
+ module EasySockets
7
+ #
8
+ # This class was created for testing purposes only. It should not be used
9
+ # in production.
10
+ #
11
+ class UdpServer
12
+ include EasySockets::ServerUtils
13
+
14
+ attr_reader :connections
15
+
16
+ DEFAULT_TIMEOUT = 0.5 # seconds
17
+
18
+ def initialize(opts={})
19
+ set_opts(opts)
20
+ @started = false
21
+ @stop_requested = false
22
+ @connections = []
23
+ register_shutdown_signals
24
+ end
25
+
26
+ def start
27
+ return if @started
28
+ @started = true
29
+ @socket = UDPSocket.new
30
+ @socket.bind('127.0.0.1', @port)
31
+ @logger.info "Listening on udp://127.0.0.1:#{@port}"
32
+ loop do
33
+ shutdown if @stop_requested
34
+ # connection = accept_non_block(@socket)
35
+ # @connections << connection
36
+ # handle(connection)
37
+ handle(@socket)
38
+ end
39
+ end
40
+
41
+ def stop
42
+ return unless @started
43
+ @stop_requested = true
44
+ end
45
+
46
+ private
47
+
48
+ def set_opts(opts)
49
+ @port = opts[:port].to_i
50
+ @port = DEFAULT_PORT if @port <= 0
51
+
52
+ @logger = opts[:logger] || Logger.new(STDOUT)
53
+
54
+ @separator = opts[:separator]
55
+ @separator ||= EasySockets::CRLF
56
+
57
+ @sleep_time = opts[:sleep_time].to_f
58
+ @sleep_time = 0.0001 if @sleep_time <= 0.0
59
+
60
+ @timeout = opts[:timeout].to_f
61
+ @timeout = DEFAULT_TIMEOUT if @timeout <= 0.0
62
+ end
63
+
64
+ def handle(connection)
65
+ loop do
66
+ shutdown if @stop_requested
67
+ begin
68
+ msg, addr = udp_read_non_block(connection)
69
+ sleep @sleep_time
70
+ unless msg.nil?
71
+ connection.send(msg, 0, addr[3], addr[1])
72
+ @logger.info "Sent: #{msg.inspect}"
73
+ end
74
+ rescue EOFError, Errno::ECONNRESET
75
+ connection.close
76
+ @logger.info 'Client disconnected.'
77
+ break
78
+ end
79
+ end
80
+ end
81
+
82
+ end
83
+ end
@@ -0,0 +1,35 @@
1
+ require 'easy_sockets/basic_socket'
2
+
3
+ module EasySockets
4
+ #
5
+ # @author Marcos Ortiz
6
+ # Subclass of {EasySockets::BasicSocket} that implement a UDP socket.
7
+ #
8
+ class UdpSocket < EasySockets::BasicSocket
9
+
10
+ #
11
+ # @param [Hash] opts the options to create a socket with.
12
+ # @option opts [Integer] :port (2000) The udp port the server is running on.
13
+ # @option opts [String] :host ('127.0.0.1') The hostname or IP address the server is running on.
14
+ #
15
+ # It also accepts all options that {EasySockets::BasicSocket#initialize} accepts
16
+ def initialize(opts={})
17
+ super(opts)
18
+
19
+ @port = opts[:port].to_i
20
+ @port = DEFAULT_PORT if @port <= 0
21
+ @host = opts[:host] || DEFAULT_HOST
22
+ end
23
+
24
+ private
25
+
26
+ def on_connect
27
+ @socket = UDPSocket.new
28
+ @socket.connect(@host, @port)
29
+ log(:debug, "Successfully connected to udp://#{@host}:#{@port}.")
30
+ rescue Exception => e
31
+ @socket.close if @socket && !@socket.closed?
32
+ raise e
33
+ end
34
+ end
35
+ end
@@ -37,6 +37,25 @@ module EasySockets
37
37
  msg
38
38
  end
39
39
 
40
+ def udp_read_non_block(connection)
41
+ total_msg = ''
42
+ addr = nil
43
+ begin
44
+ msg, addr = connection.recvfrom_nonblock(CHUNK_SIZE)
45
+ total_msg << msg
46
+ while !total_msg.end_with?(@separator) do
47
+ msg, addr = connection.recvfrom_nonblock(EasySockets::CHUNK_SIZE)
48
+ total_msg << msg
49
+ end
50
+ @logger.info "Got: #{total_msg.inspect}" unless total_msg.nil? || total_msg.empty?
51
+ total_msg.empty? ? nil : [total_msg, addr]
52
+ rescue IO::WaitReadable
53
+ if IO.select([connection], nil, nil, @timeout)
54
+ retry
55
+ end
56
+ end
57
+ end
58
+
40
59
  def write_non_block(connection, msg)
41
60
  return 0 unless msg && msg.is_a?(String)
42
61
  total_bytes = 0
@@ -1,3 +1,3 @@
1
1
  module EasySockets
2
- VERSION = "0.1.0"
2
+ VERSION = "1.0.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: easy_sockets
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Marcos Ortiz
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-06-30 00:00:00.000000000 Z
11
+ date: 2016-07-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -66,7 +66,7 @@ files:
66
66
  - ".rspec"
67
67
  - ".travis.yml"
68
68
  - ".yardopts"
69
- - CHANGELOG.rb
69
+ - CHANGELOG.md
70
70
  - Gemfile
71
71
  - LICENSE.txt
72
72
  - README.md
@@ -75,12 +75,15 @@ files:
75
75
  - bin/setup
76
76
  - easy_sockets.gemspec
77
77
  - examples/tcp_socket.rb
78
+ - examples/udp_socket.rb
78
79
  - examples/unix_socket.rb
79
80
  - lib/easy_sockets.rb
80
81
  - lib/easy_sockets/basic_socket.rb
81
82
  - lib/easy_sockets/constants.rb
82
83
  - lib/easy_sockets/tcp/tcp_server.rb
83
84
  - lib/easy_sockets/tcp/tcp_socket.rb
85
+ - lib/easy_sockets/udp/udp_server.rb
86
+ - lib/easy_sockets/udp/udp_socket.rb
84
87
  - lib/easy_sockets/unix/unix_server.rb
85
88
  - lib/easy_sockets/unix/unix_socket.rb
86
89
  - lib/easy_sockets/utils.rb
@@ -111,3 +114,4 @@ signing_key:
111
114
  specification_version: 4
112
115
  summary: Wrapper around ruby socket stdlib to make developer's life easier'.
113
116
  test_files: []
117
+ has_rdoc: