async_tcpsocket 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.
Files changed (3) hide show
  1. checksums.yaml +15 -0
  2. data/lib/async_tcpsocket.rb +148 -0
  3. metadata +65 -0
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ ZWJlMmUxZDYzMzJmMDliZjQwOTQ3NDZiYWNjMDk2ZjkxZDgwNWQ4ZA==
5
+ data.tar.gz: !binary |-
6
+ M2JjNzY2ZjYxMDQzNGRiMmJhOTE3YmRmOTEwYzZlYTA5MmY3N2UwNw==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ NWQ0NjVlZmUyOTMyNTUxNThlYmRmNDI1NzQ3ZWIyMGZhOTg1MzVhOGY5YmI5
10
+ ZGQ0NTgwMGM3YmYyNTViY2MxYmQyZTZiOTU5ZjM2MWE5MTc4NTNjMTRiNDBk
11
+ MzMwNTI1ZDljNjJkOTU2Y2IyMThhM2QzNDkzODgyM2JjYzE3NDA=
12
+ data.tar.gz: !binary |-
13
+ ZmY5MjYzNTNlYmE5NjEwNWMxODRjMWNmMjc3OTA0MzA2NDYyZDg4NTgxZWM4
14
+ MjExZTc2ZGY1NmI3ZjYyYTc1NDYyZDYwNDYwZWY4NDQyM2JkMTY3ZDg4ZWY4
15
+ YjhmZjBhMTY1YTI2ZjBmODZiMDY2MjQ2NjFiZGUxYmE4ZjU0NzY=
@@ -0,0 +1,148 @@
1
+ require 'socket'
2
+ require 'thread'
3
+ require 'async_emitter'
4
+
5
+ #######################################################################
6
+ # An asyncronous TCP socket implementation (wraps TCPSocket)
7
+ #
8
+ # Inherits AsyncEmitter and emits three events, :data, :close and :error.
9
+ # :data is emitted when data is recieved,
10
+ # :close is emitted if the other side closes the connection and it is detected,
11
+ # :error emits errors
12
+ #
13
+ # ==Example
14
+ #
15
+ # require 'async_tcpsocket'
16
+ #
17
+ # socket = AsyncTCPSocket.new
18
+ #
19
+ # socket.once :error, Proc.new { |err|
20
+ # STDERR.puts "Error: #{err}"
21
+ # socket.close
22
+ # }
23
+ #
24
+ # socket.once :close, Proc.new { |err|
25
+ # socket.close
26
+ # }
27
+ #
28
+ # socket.on :data, Proc.new { |data|
29
+ # puts "#{data}"
30
+ # }
31
+ #
32
+ # socket.connect 'localhost', 80
33
+ # socket.puts "GET / HTTP 1.1\r\n\r\n"
34
+ #
35
+ # #wait for return key
36
+ # gets
37
+ #
38
+ # socket.close
39
+ #
40
+ # @author Greg Martin
41
+ ##########################################################################
42
+ class AsyncTCPSocket < AsyncEmitter
43
+
44
+ #################################################################
45
+ # constructor
46
+ #
47
+ # @param socket [TCPSocket] or nil
48
+ #################################################################
49
+ def initialize (socket=nil)
50
+ super()
51
+ @socket = socket
52
+ @write_data = nil
53
+ @write_semaphore = Mutex.new
54
+ @write_cv = ConditionVariable.new
55
+
56
+ if socket != nil
57
+ threads
58
+ end
59
+ end
60
+
61
+ #################################################################
62
+ # connect to a server - if the socket is already connected it
63
+ # will be closed
64
+ #
65
+ # @param host [String] the server host address
66
+ # @param port [FixedNum] the server port
67
+ #################################################################
68
+ def connect (host, port)
69
+ close
70
+
71
+ begin
72
+ @socket = TCPSocket.new host, port
73
+ rescue Exception => e
74
+ emit :error, e
75
+ end
76
+
77
+ threads
78
+ end
79
+
80
+ ################################################################
81
+ # closes the connection
82
+ ###############################################################
83
+ def close
84
+ if @socket != nil
85
+ @socket.close
86
+ Thread.kill @read_thread
87
+ Thread.kill @write_thread
88
+ @socket = nil
89
+ end
90
+ end
91
+
92
+ ################################################################
93
+ # sends data asyncronously - non-string objects will need to be
94
+ # serialized
95
+ #
96
+ # @param data [Object] - the data to send
97
+ # #############################################################
98
+ def puts data
99
+ @write_semaphore.synchronize do
100
+ @write_data = data
101
+ @write_cv.signal
102
+ end
103
+ end
104
+
105
+ protected
106
+ def threads
107
+ init_sem = Mutex.new
108
+ cv = ConditionVariable.new
109
+
110
+ @read_thread = Thread.new do
111
+ loop do
112
+ data = @socket.gets
113
+ if data == nil
114
+ e = Exception.exception ("socket closed")
115
+ emit :close, e
116
+ break
117
+ else
118
+ emit :data, data
119
+ end
120
+ end
121
+ end
122
+
123
+ @write_thread = Thread.new do
124
+ loop do
125
+ @write_semaphore.synchronize do
126
+ init_sem.synchronize do
127
+ cv.signal
128
+ end
129
+
130
+ @write_cv.wait @write_semaphore
131
+ begin
132
+ @socket.puts @write_data
133
+ rescue Exception => e
134
+ emit :error, e
135
+ end
136
+
137
+ end
138
+ end
139
+ end
140
+
141
+ init_sem.synchronize do
142
+ cv.wait init_sem
143
+ end
144
+
145
+ end
146
+
147
+ end
148
+
metadata ADDED
@@ -0,0 +1,65 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: async_tcpsocket
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Greg Martin
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-04-29 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: async_emitter
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.1'
20
+ - - ! '>='
21
+ - !ruby/object:Gem::Version
22
+ version: 1.1.1
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: '1.1'
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: 1.1.1
33
+ description: An asyncronous tcp socket for ruby
34
+ email: greg@softsprocket.com
35
+ executables: []
36
+ extensions: []
37
+ extra_rdoc_files: []
38
+ files:
39
+ - lib/async_tcpsocket.rb
40
+ homepage: http://rubygems.org/gems/async_tcpsocket.rb
41
+ licenses:
42
+ - MIT
43
+ metadata: {}
44
+ post_install_message:
45
+ rdoc_options: []
46
+ require_paths:
47
+ - lib
48
+ required_ruby_version: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - ! '>='
51
+ - !ruby/object:Gem::Version
52
+ version: '0'
53
+ required_rubygems_version: !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - ! '>='
56
+ - !ruby/object:Gem::Version
57
+ version: '0'
58
+ requirements: []
59
+ rubyforge_project:
60
+ rubygems_version: 2.4.6
61
+ signing_key:
62
+ specification_version: 4
63
+ summary: AsyncTCPServer
64
+ test_files: []
65
+ has_rdoc: