minitcp 0.10.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 +7 -0
- data/CHANGELOG.txt +42 -0
- data/LICENSE +2 -0
- data/README.md +200 -0
- data/Rakefile.rb +217 -0
- data/VERSION +1 -0
- data/lib/minitcp.rb +341 -0
- data/minitcp.gemspec +37 -0
- data/samples/README.md +19 -0
- data/samples/name_server.rb +131 -0
- data/samples/pingpongplot.rb +26 -0
- data/samples/plot.rb +190 -0
- data/samples/proxy.rb +46 -0
- data/samples/relay/README.md +41 -0
- data/samples/relay/c.rb +21 -0
- data/samples/relay/relai_config.data +4 -0
- data/samples/relay/relaiproxy.rb +180 -0
- data/samples/relay.rb +102 -0
- data/samples/spdy.rb +43 -0
- data/samples/statcpu.rb +37 -0
- data/test.rb +192 -0
- metadata +72 -0
data/lib/minitcp.rb
ADDED
@@ -0,0 +1,341 @@
|
|
1
|
+
# LGPL, Author: Regis d'Aubarede <regis.aubarede@gmail.com>
|
2
|
+
#
|
3
|
+
##############################################################
|
4
|
+
# minitcp.rb
|
5
|
+
##############################################################
|
6
|
+
|
7
|
+
require 'thread'
|
8
|
+
require 'timeout'
|
9
|
+
require 'socket'
|
10
|
+
require 'gserver'
|
11
|
+
|
12
|
+
|
13
|
+
module SocketReactive
|
14
|
+
|
15
|
+
def data_readed=(v) @data_readed=v end
|
16
|
+
def data_readed() @data_readed||="" end
|
17
|
+
|
18
|
+
# read n byte, block the caller, return nil if socket if close
|
19
|
+
# if block is defined, it is yield with data, method return whith the value of yield
|
20
|
+
# if looping is true, the method loop until socket close, (or current thread is killed)
|
21
|
+
def receive_n_bytes(sizemax,looping=false,&b)
|
22
|
+
s=sizemax
|
23
|
+
if self.data_readed.size>=sizemax
|
24
|
+
buff,self.data_readed=self.data_readed[0..sizemax-1],self.data_readed[sizemax..-1]
|
25
|
+
buff=b.call(buff) if block_given?
|
26
|
+
return buff unless looping
|
27
|
+
end
|
28
|
+
s=sizemax-self.data_readed.size
|
29
|
+
loop do
|
30
|
+
#p ["waiting ",s,data_readed]
|
31
|
+
sd=s>1024 ? 1024 : s
|
32
|
+
data=(self.recv(sd) rescue nil)
|
33
|
+
#p "nrec: w#{sizemax}/ rec:#{(data||'').size} / #{sd} old=#{data_readed.size} /// #{(data||'').size<70 ? data : "."}"
|
34
|
+
if data && data.size>0
|
35
|
+
self.data_readed=self.data_readed+data
|
36
|
+
s=sizemax-self.data_readed.size
|
37
|
+
if s<=0
|
38
|
+
buff,self.data_readed=self.data_readed,""
|
39
|
+
s=sizemax
|
40
|
+
buff=b.call(buff) if block_given?
|
41
|
+
return buff unless looping
|
42
|
+
end
|
43
|
+
else
|
44
|
+
close rescue nil
|
45
|
+
break # socket close
|
46
|
+
end
|
47
|
+
end #loop
|
48
|
+
end
|
49
|
+
# wait n byte or timeout. if block is defined, it is yielded with data
|
50
|
+
# return nil if timeout/socket closed, or data if no bloc, or yield value
|
51
|
+
def received_n_timeout(sizemax,timeout_ms,&b)
|
52
|
+
timeout(timeout_ms/1000.0) {
|
53
|
+
ret=receive_n_bytes(sizemax,false,&b)
|
54
|
+
return ret
|
55
|
+
}
|
56
|
+
rescue Timeout::Error
|
57
|
+
return nil
|
58
|
+
rescue Exception => e
|
59
|
+
$stdout.puts "#{e} :\n #{e.backtrace.join("\n ")}"
|
60
|
+
end
|
61
|
+
|
62
|
+
def received_any_timeout(sizemax,timeout_ms)
|
63
|
+
timeout(timeout_ms/1000.0) {
|
64
|
+
return recv(sizemax)
|
65
|
+
}
|
66
|
+
rescue Timeout::Error
|
67
|
+
return nil
|
68
|
+
rescue Exception => e
|
69
|
+
$stdout.puts "#{e} :\n #{e.backtrace.join("\n ")}"
|
70
|
+
end
|
71
|
+
|
72
|
+
# async wait and read data on socket, yield values readed,
|
73
|
+
# return thread spawned, which can be kill
|
74
|
+
def on_any_receive()
|
75
|
+
Thread.new() do
|
76
|
+
begin
|
77
|
+
if self.data_readed.size>0
|
78
|
+
buff,self.data_readed=self.data_readed,""
|
79
|
+
yield(buff)
|
80
|
+
end
|
81
|
+
loop do
|
82
|
+
data=(self.recv(64*1024) rescue nil)
|
83
|
+
data && data.size>0 ? yield(data) : break
|
84
|
+
end
|
85
|
+
rescue Exception => e
|
86
|
+
$stdout.puts "#{e} :\n #{e.backtrace.join("\n ")}"
|
87
|
+
end
|
88
|
+
close rescue nil
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
|
93
|
+
# async yield on received n bytes
|
94
|
+
# return thread spawned, which can be kill
|
95
|
+
def on_n_receive(sizemax=1,&b)
|
96
|
+
Thread.new() do
|
97
|
+
begin
|
98
|
+
receive_n_bytes(sizemax,true,&b)
|
99
|
+
rescue Exception => e
|
100
|
+
$stdout.puts "#{e} :\n #{e.backtrace.join("\n ")}"
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
# read until separator reached, block the caller, return nil if socket is close
|
106
|
+
# if block is defined, it is yield with data, method return whith the value of yield
|
107
|
+
# if looping is true, the method loop until socket close, (or current thread is killed)
|
108
|
+
# this read some extra data. they can be retrieve with in socket.data_readed.
|
109
|
+
# data_readed is use for next calls to receives_n_byte/receive_sep
|
110
|
+
def receive_sep(separator,sizemax=1024,looping=false,&b)
|
111
|
+
if self.data_readed.size>0
|
112
|
+
a=self.data_readed.split(separator,2)
|
113
|
+
while a.size>1
|
114
|
+
buff= a.size>2 ? a[0..-2] : a.first
|
115
|
+
self.data_readed=a.last
|
116
|
+
buff=b.call(buff) if block_given?
|
117
|
+
return buff unless looping
|
118
|
+
a=self.data_readed.split(separator,2)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
loop do
|
122
|
+
data=(self.recv(sizemax-self.data_readed.size) rescue nil)
|
123
|
+
if data && data.size>0
|
124
|
+
self.data_readed=self.data_readed+data
|
125
|
+
a=(self.data_readed).split(separator,2)
|
126
|
+
while a.size>1
|
127
|
+
buff= a.size>2 ? a[0..-2] : a.first
|
128
|
+
self.data_readed=a.last
|
129
|
+
buff=b.call(buff) if block_given?
|
130
|
+
return buff unless looping
|
131
|
+
a=(self.data_readed).split(separator,2)
|
132
|
+
end
|
133
|
+
else
|
134
|
+
close rescue nil
|
135
|
+
break
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
# async yield on received data until end-buffer string
|
141
|
+
# end-buffer can be string or regexp (args of data.split(,2))
|
142
|
+
# return thread spawned, which can be kill
|
143
|
+
# this read some extra data. they can be retrieve with in socket.data_readed.
|
144
|
+
# data_readed is use for next calls to receives_n_byte/receive_sep
|
145
|
+
def on_receive_sep(separator,sizemax=1024,&b)
|
146
|
+
Thread.new() do
|
147
|
+
begin
|
148
|
+
receive_sep(separator,sizemax,looping=true,&b)
|
149
|
+
rescue Exception => e
|
150
|
+
$stdout.puts "#{e} :\n #{e.backtrace.join("\n ")}"
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
# async yield after a duration, if socket is open
|
156
|
+
# return thread spawned, which can be kill
|
157
|
+
def after(duration_ms)
|
158
|
+
Thread.new() do
|
159
|
+
begin
|
160
|
+
sleep(duration_ms/1000.0)
|
161
|
+
yield unless self.connected?()
|
162
|
+
rescue Exception => e
|
163
|
+
$stdout.puts "#{e} :\n #{e.backtrace.join("\n ")}"
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
# async yield periodicaly, if socket is open
|
169
|
+
# return thread spawned, which can be kill
|
170
|
+
def on_timer(value=1000)
|
171
|
+
Thread.new() {
|
172
|
+
begin
|
173
|
+
nbtick=(value/TICK)+1
|
174
|
+
loop do
|
175
|
+
i=0
|
176
|
+
sleep(TICK/1000.0) while self.connected?() && (i+=1)<nbtick
|
177
|
+
self.connected?() ? yield() : break
|
178
|
+
end
|
179
|
+
rescue Exception => e
|
180
|
+
$stdout.puts "#{e} :\n #{e.backtrace.join("\n ")}"
|
181
|
+
end
|
182
|
+
}
|
183
|
+
end
|
184
|
+
|
185
|
+
# wait until curent socket is close.
|
186
|
+
def wait_end()
|
187
|
+
begin
|
188
|
+
loop do
|
189
|
+
sleep(TICK/1000.0) while (self.connected?() rescue nil)
|
190
|
+
break
|
191
|
+
end
|
192
|
+
rescue Exception => e
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
# Test if a socket is open. (use socket.remote_address() !)
|
197
|
+
def connected?()
|
198
|
+
(self.remote_address rescue nil) ? true : false
|
199
|
+
end
|
200
|
+
# duration of sleep when active wait (wait_end,on_timer...)
|
201
|
+
TICK=600
|
202
|
+
|
203
|
+
def self.make_socket_reactive(socket)
|
204
|
+
socket.extend(SocketReactive)
|
205
|
+
socket.data_readed=""
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
# Assure connection to server, extend socket connection by SocketReactive module.
|
210
|
+
#
|
211
|
+
# MClient.run_one_shot("localhost",2200) do |socket| .. end.join
|
212
|
+
#
|
213
|
+
# MClient.run_continous("localhost",2200,6000) do |socket| .. end.join
|
214
|
+
#
|
215
|
+
class MClient
|
216
|
+
# maintain a conntection to a TCP serveur, sleep timer_interconnection_ms millisecondes
|
217
|
+
# beetwen each reconnections
|
218
|
+
def self.run_continious(host,port,timer_interconnection_ms,&b)
|
219
|
+
Thread.new do
|
220
|
+
loop { run_one_shot(host,port,&b).join ; sleep timer_interconnection_ms/1000.0 }
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
def self.run_continous(host,port,timer_interconnection,&b)
|
225
|
+
self.run_continious(host,port,timer_interconnection,&b)
|
226
|
+
end
|
227
|
+
|
228
|
+
# Connecte to a TCP server, call block with client socket if connection sucess.
|
229
|
+
# enssure close connection after end of block
|
230
|
+
def self.run_one_shot(host="localhost",port=80)
|
231
|
+
begin
|
232
|
+
sleep(0.03) # give some time for server ready (for test...)
|
233
|
+
socket = TCPSocket.new(host,port)
|
234
|
+
rescue
|
235
|
+
puts "not connected to #{host}:#{port}: " + $!.to_s
|
236
|
+
return (Thread.new {})
|
237
|
+
end
|
238
|
+
SocketReactive::make_socket_reactive(socket)
|
239
|
+
Thread.new do
|
240
|
+
begin
|
241
|
+
yield(socket)
|
242
|
+
rescue Exception => e
|
243
|
+
puts "#{e}\n #{e.backtrace.join("\n ")}"
|
244
|
+
ensure
|
245
|
+
socket.close() rescue nil
|
246
|
+
end
|
247
|
+
end
|
248
|
+
end
|
249
|
+
end
|
250
|
+
|
251
|
+
|
252
|
+
# Assure connection to server, extend socket connection by SocketReactive module.
|
253
|
+
#
|
254
|
+
# MClient.run_one_shot("localhost",2200) do |socket| .. end.join
|
255
|
+
#
|
256
|
+
# MClient.run_continous("localhost",2200,6000) do |socket| .. end.join
|
257
|
+
#
|
258
|
+
class UDPAgent
|
259
|
+
# maintain a conntection to a TCP serveur, sleep timer_interconnection_ms millisecondes
|
260
|
+
# beetwen each reconnections
|
261
|
+
def self.send_datagram(host,port,mess)
|
262
|
+
sock = UDPSocket.new
|
263
|
+
#p ["sock.send",mess, 0, host, port]
|
264
|
+
sock.send(mess, 0, host, port)
|
265
|
+
sock.close
|
266
|
+
end
|
267
|
+
def self.send_datagram_on_socket(socket,host,port,mess)
|
268
|
+
socket.send(mess, 0, host, port)
|
269
|
+
end
|
270
|
+
|
271
|
+
Thread.abort_on_exception=true
|
272
|
+
|
273
|
+
# send datagram on timer
|
274
|
+
def self.on_timer(periode,options)
|
275
|
+
Thread.new do
|
276
|
+
sleep periode/1000.0
|
277
|
+
sock = UDPSocket.new
|
278
|
+
if options[:port]
|
279
|
+
sock.bind("0.0.0.0", options[:port])
|
280
|
+
end
|
281
|
+
loop do
|
282
|
+
rep=IO.select([sock],nil,nil,periode/1000.0)
|
283
|
+
#puts "IO.SELECT => #{rep}"
|
284
|
+
if rep
|
285
|
+
Thread.new {
|
286
|
+
data,peer=sock.recvfrom(1024)
|
287
|
+
options[:on_receive].call(data,peer,sock)
|
288
|
+
} if options[:on_receive]
|
289
|
+
elsif options[:on_timer]
|
290
|
+
h=options[:on_timer].call()
|
291
|
+
self.send_datagram_on_socket(sock,h[:host], h[:port],h[:mess]) if h && h[:mess] && h[:host] && h[:port]
|
292
|
+
end
|
293
|
+
end
|
294
|
+
end
|
295
|
+
end
|
296
|
+
# recieved UDP datagramme, bloc can ellaborate a reply, which will be sending to client
|
297
|
+
def self.on_datagramme(host,port)
|
298
|
+
serv = UDPSocket.new
|
299
|
+
serv.bind(host, port)
|
300
|
+
Thread.new do
|
301
|
+
loop do
|
302
|
+
begin
|
303
|
+
Thread.new(*serv.recvfrom(1024)) do |data,peer| # peer=["AF_INET", 59340, "127.0.0.1", "127.0.0.1"]
|
304
|
+
proto,cli_port,srv_addr,cli_addr=*peer
|
305
|
+
response=yield(data,cli_addr,cli_port)
|
306
|
+
self.send_datagram_on_socket(serv,cli_addr,cli_port,response) if response
|
307
|
+
end
|
308
|
+
rescue Exception => e
|
309
|
+
puts "#{e}\n #{e.backtrace.join("\n ")}"
|
310
|
+
ensure
|
311
|
+
end
|
312
|
+
end
|
313
|
+
end
|
314
|
+
end
|
315
|
+
end
|
316
|
+
|
317
|
+
# Run a TCP serveur, with a max connection simultaneous,
|
318
|
+
# When connection succes, call the bloc given with socket (extended by SocketReactive).
|
319
|
+
#
|
320
|
+
# MServer( "8080" , "0.0.0.0" ,1) { |socket| loop { p socket.gets} }
|
321
|
+
class MServer < GServer
|
322
|
+
def self.service(port,host,max,&b)
|
323
|
+
srv=new(port,host,max,&b)
|
324
|
+
srv.audit = true
|
325
|
+
srv.start
|
326
|
+
srv
|
327
|
+
end
|
328
|
+
def initialize(port,host,max=1,&b)
|
329
|
+
super(port,host,max)
|
330
|
+
@bloc=b
|
331
|
+
end
|
332
|
+
def serve( io )
|
333
|
+
SocketReactive::make_socket_reactive(io)
|
334
|
+
begin
|
335
|
+
@bloc.call(io)
|
336
|
+
rescue Exception => e
|
337
|
+
puts "Error in Mserver block: #{e} :\n #{e.backtrace.join("\n ")}"
|
338
|
+
end
|
339
|
+
end
|
340
|
+
end
|
341
|
+
|
data/minitcp.gemspec
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push('lib')
|
3
|
+
|
4
|
+
Gem::Specification.new do |s|
|
5
|
+
s.name = "minitcp"
|
6
|
+
s.licenses = ['LGPL']
|
7
|
+
s.version = File.read("VERSION").strip
|
8
|
+
s.date = Time.now.to_s.split(/\s+/)[0]
|
9
|
+
s.email = "regis.aubarede@gmail.com"
|
10
|
+
s.homepage = "https://github.com/glurp/minitcp"
|
11
|
+
s.authors = ["Regis d'Aubarede"]
|
12
|
+
s.summary = "A DSL for programming little Tcp client and server"
|
13
|
+
s.description = <<EEND
|
14
|
+
A DSL for programming little Tcp client and server
|
15
|
+
EEND
|
16
|
+
|
17
|
+
dependencies = [
|
18
|
+
]
|
19
|
+
|
20
|
+
s.files = Dir['**/*'].reject { |a| a =~ /^\.git/ || a =~ /\._$/ || a =~ /\.~$/}
|
21
|
+
s.test_files = Dir['samples/**']
|
22
|
+
s.require_paths = ["lib"]
|
23
|
+
|
24
|
+
## Make sure you can build the gem on older versions of RubyGems too:
|
25
|
+
s.rubygems_version = "1.8.15"
|
26
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
27
|
+
s.specification_version = 3 if s.respond_to? :specification_version
|
28
|
+
|
29
|
+
dependencies.each do |type, name, version|
|
30
|
+
if s.respond_to?("add_#{type}_dependency")
|
31
|
+
s.send("add_#{type}_dependency", name, version)
|
32
|
+
else
|
33
|
+
s.add_dependency(name, version)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
data/samples/README.md
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
Minitcp usages
|
2
|
+
===
|
3
|
+
|
4
|
+
**proxy.rb** : real tcp proxy
|
5
|
+
|
6
|
+
**name_server.rb** : my dns service :)
|
7
|
+
|
8
|
+
**relay.rb** : not ready , tcp relay for bypass firewall/proxy protection
|
9
|
+
|
10
|
+
*spdy.rb** : SPDY server relay for http server
|
11
|
+
|
12
|
+
Dynamic ploting
|
13
|
+
===
|
14
|
+
|
15
|
+
**plot.rb** : realy no tcp... , plot measures on stdin to screen
|
16
|
+
|
17
|
+
**pingpongplot.rb** : measure connection time to google.com (for piping to plot.rb)
|
18
|
+
|
19
|
+
**statcpu.rb** : linux : cpu time to stdout, for piping to plot.rb
|
@@ -0,0 +1,131 @@
|
|
1
|
+
# LGPL, Author: Regis d'Aubarede <regis.aubarede@gmail.com>
|
2
|
+
#################################################################
|
3
|
+
# name_server.rb
|
4
|
+
#################################################################
|
5
|
+
require_relative '../lib/minitcp.rb'
|
6
|
+
|
7
|
+
BasicSocket.do_not_reverse_lookup = true
|
8
|
+
Thread.abort_on_exception = true
|
9
|
+
|
10
|
+
$SIZE=30
|
11
|
+
$dico_name={}
|
12
|
+
$dico_ip={}
|
13
|
+
|
14
|
+
def run_net_relay()
|
15
|
+
MServer.service(4410,"0.0.0.0",1000) do |socket|
|
16
|
+
socket.on_n_receive($SIZE) do |data|
|
17
|
+
ip=socket.remote_address.ip_address
|
18
|
+
cmd,url,http=data.split(' ')
|
19
|
+
name,method,*args=url.split('/').last
|
20
|
+
next if cmd!="GET"
|
21
|
+
case method
|
22
|
+
when "server"
|
23
|
+
old=ActiveConnection.search(name)
|
24
|
+
if old && old.state==:free
|
25
|
+
old.deconnect
|
26
|
+
old=nil
|
27
|
+
end
|
28
|
+
if !old || old.state==:connected
|
29
|
+
ActiveConnection.add(socket)
|
30
|
+
end
|
31
|
+
when "client"
|
32
|
+
if srv=ActiveConnection.search(args.first)
|
33
|
+
srv.connect_to(name)
|
34
|
+
else
|
35
|
+
smess("NOTCONNECT")
|
36
|
+
end
|
37
|
+
end
|
38
|
+
rep=""
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def smess(socket,*args)
|
44
|
+
data= args.join(";")+";"
|
45
|
+
socket.send(data+" "*($SIZE-data.length),0) rescue p $!
|
46
|
+
end
|
47
|
+
|
48
|
+
def run_server_name()
|
49
|
+
MServer.service(4400,"0.0.0.0",100) do |socket|
|
50
|
+
socket.on_n_receive($SIZE) do |data|
|
51
|
+
ip=socket.remote_address.ip_address
|
52
|
+
cmd,*args=data.split(";")
|
53
|
+
name=args.first
|
54
|
+
rep=""
|
55
|
+
case cmd
|
56
|
+
when "update"
|
57
|
+
$dico_name[name]=ip
|
58
|
+
$dico_ip[ip]=name
|
59
|
+
rep="OK"
|
60
|
+
when "forget"
|
61
|
+
oldip=$dico_ip[ip]
|
62
|
+
if oldip && $dico_ip[ip]==name && $dico_name[name]==ip
|
63
|
+
$dico_name.delete(name)
|
64
|
+
$dico_ip.delete(ip)
|
65
|
+
rep="OK"
|
66
|
+
end
|
67
|
+
when "get"
|
68
|
+
rep=$dico_name[name].to_s
|
69
|
+
when "geti"
|
70
|
+
rep=$dico_ip[name].to_s
|
71
|
+
end
|
72
|
+
rep.size>0 ? smess(socket,"ACK",name,rep) : smess(socket,"NACK","NOK","NOK")
|
73
|
+
end
|
74
|
+
socket.after(10*1000) { socket.close rescue nil}
|
75
|
+
socket.wait_end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
################# Client api ########################
|
80
|
+
|
81
|
+
def update_server_name(hostname)
|
82
|
+
MClient.run_one_shot("localhost",4400) do |socket|
|
83
|
+
socket.on_n_receive($SIZE) { |data| p data ; socket.close }
|
84
|
+
smess(socket,"update",hostname)
|
85
|
+
socket.wait_end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
def fetch_name(hostname)
|
89
|
+
ret=""
|
90
|
+
MClient.run_one_shot("localhost",4400) do |socket|
|
91
|
+
socket.on_n_receive($SIZE) { |data| ret= data.split(";")[2] ; socket.close }
|
92
|
+
smess(socket,"get",hostname)
|
93
|
+
socket.wait_end
|
94
|
+
ret
|
95
|
+
end.join
|
96
|
+
ret
|
97
|
+
end
|
98
|
+
def fetch_ip(ip)
|
99
|
+
ret=""
|
100
|
+
MClient.run_one_shot("localhost",4400) do |socket|
|
101
|
+
socket.on_n_receive($SIZE) { |data| ret= data.split(";")[2] ; socket.close }
|
102
|
+
smess(socket,"geti",ip)
|
103
|
+
socket.wait_end
|
104
|
+
ret
|
105
|
+
end.join
|
106
|
+
ret
|
107
|
+
end
|
108
|
+
def forget_me(name)
|
109
|
+
MClient.run_one_shot("localhost",4400) do |socket|
|
110
|
+
ret="?"
|
111
|
+
socket.on_n_receive($SIZE) { |data| ret= data.split(";")[2] ; socket.close }
|
112
|
+
smess(socket,"forget",name)
|
113
|
+
socket.wait_end
|
114
|
+
p "forget : #{ret}"
|
115
|
+
end.join
|
116
|
+
end
|
117
|
+
|
118
|
+
if $0==__FILE__
|
119
|
+
run_server_name
|
120
|
+
|
121
|
+
Thread.new { 4.times { update_server_name("glurp") ; sleep 1 } }
|
122
|
+
Thread.new { 4.times { update_server_name("glurp22") ; sleep 1 } }
|
123
|
+
|
124
|
+
sleep 2
|
125
|
+
puts "\n\n***************** get name *******************\n\n"
|
126
|
+
|
127
|
+
p fetch_name("glurp")
|
128
|
+
p fetch_ip("127.0.0.1")
|
129
|
+
forget_me("glurp22")
|
130
|
+
sleep
|
131
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# LGPL, Author: Regis d'Aubarede <regis.aubarede@gmail.com>
|
2
|
+
#################################################################
|
3
|
+
# pingpongplot.rb : measure pingpong time on google, plot it
|
4
|
+
#
|
5
|
+
# Usage :
|
6
|
+
# > ruby pingpongplot.rb | ruby plot.rb 0 0 300 pingpong auto
|
7
|
+
#################################################################
|
8
|
+
require_relative '../lib/minitcp.rb'
|
9
|
+
|
10
|
+
|
11
|
+
$stdout.sync=true
|
12
|
+
|
13
|
+
MClient.run_continious("google.com",80,100) do |socket|
|
14
|
+
s=Time.now.to_f
|
15
|
+
socket.on_receive_sep("\r\n") do |data|
|
16
|
+
$stdout.puts("#{(Time.now.to_f-s)*1000}")
|
17
|
+
socket.close rescue nil
|
18
|
+
Thread.current.kill
|
19
|
+
end
|
20
|
+
s=Time.now.to_f
|
21
|
+
socket.print "GET /blabla HTTP/1.0\r\n\r\n"
|
22
|
+
socket.wait_end
|
23
|
+
end
|
24
|
+
|
25
|
+
|
26
|
+
sleep
|