aboutsummaryrefslogtreecommitdiff
path: root/externals/gridflow/extra/server_2.rb
blob: 4807d50272ff25d77cee74e7920fabfa62c44663 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# a server program to connect 2 or more clients together.
# by Mathieu Bouchard

require "fcntl"
require "socket"

class IO
  def nonblock=flag
    bit = Fcntl::O_NONBLOCK
    fcntl(Fcntl::F_SETFL, (fcntl(Fcntl::F_GETFL) & ~bit) |
      if flag then bit else 0 end)
  end
  # does not work with any ruby version, due to a bug. see below.
  def read_at_most n
    s=""
    k=1<<(Math.log(n)/Math.log(2)).to_i
    while k>0
      unless k+s.length>n
        puts "trying #{k}"
        (s << read(k)) rescue Errno::EWOULDBLOCK
      end
      k>>=1
    end
    s
  end
  # this one works but is slow.
  def bugfree_read_at_most n
    s=""
    (s << (read 1) while s.length<n) rescue Errno::EWOULDBLOCK
    s 
  end
end

serv = TCPServer.new 4242
socks = [serv]

loop {
  puts "waiting for connection (port 4242)"
  begin
    loop {
      puts "waiting"
      ready,blah,crap = IO.select socks, [], socks, 1
      (ready||[]).each {|s|
	if s==serv then
          sock = serv.accept
          sock.nonblock=true
          socks << sock
          puts "incoming connection (total: #{socks.length-1})"
	else
          other = socks.find_all{|x|not TCPServer===x} - [s]
          stuff = s.bugfree_read_at_most 1024
          p stuff
          (s.close; socks.delete s) if not stuff or stuff.length==0
          other.each {|x|
            p x
            x.write stuff
          }
        end
      }
    }
  rescue Errno::EPIPE # Broken Pipe
    puts "connection closed (by client)"
    # it's ok, go back to waiting.
  end
}