Rubyでサーバを作ってクライアントにデータを配信 vol.4

スレッドなどでそれぞれ待ち受けるという手もありますが、 IOの入出力を待つ手段としては一般的ではないようです。 IOの動きを監視して待ち受け、動きがあったら場合分けをして 処理をするのが一般的なようです。 これをReactorパターンといいます。 IO.selectで配列を引数に入れると、 引数で入れたものに動きがあるまで待ち続けます。 動きがあると、次のステップに進むので、そこで場合分けをして処理をします。

require "socket"

port = if ARGV[0] then ARGV[0] else 'echo' end
gate = TCPServer.open(port)

sockets = [gate, STDIN]
clients = []
loop do
  r_sockets = IO.select(sockets+clients)[0]
  r_sockets.each do |socket|
    case socket
    when STDIN
      str = socket.gets
      clients.each do |client|
        client.puts str.upcase
      end
    when TCPServer
      client = socket.accept
      clients << client
      p clients
    when TCPSocket
      unless socket.eof?
        str=socket.gets
        socket.puts str.upcase
      else
        socket.close
        clients.delete(socket)
        p clients
      end
    end
  end
end

gate.close

いくつも同時に接続して、配信可能です。 f:id:xibbar:20150817141657p:plain

Rubyでサーバを作ってクライアントにデータを配信 vol.3

forkはダメです。forkは別プロセスを立ち上げるので、メモリの共有ができません。 なので、同じデータの一斉配信には向いていません。プロセス間通信とか仕組みが面倒です。

ちゃんと動かないプログラムをとりあえず書いてみました。

require "socket"

port = if ARGV[0] then ARGV[0] else 'echo' end
gate = TCPServer.open(port)

clients = []
pid=Process.pid
fork
if pid == Process.pid
  loop do
    clients << gate.accept
    p clients
  end
else
  while msg = STDIN.gets
    p clients
    clients.each do |client|
      if client.closed?
        clients.delete client
      else
        begin
          client.puts msg.upcase
        rescue

        end
      end
    end
  end
end
gate.close

いきなりforkして、接続待ちと書き出しを別々のプロセスでやっているという 意味のないプログラムです。

Rubyでサーバを作ってクライアントにデータを配信 vol.2

vol.1 のサーバだと、1対1の通信しかできません。これだとサーバ&クライアント型の プログラムとは言い難いので、サーバ1台に対し、クライアント複数台で作ってみます。

require "socket"

port = if ARGV[0] then ARGV[0] else 'echo' end
gate = TCPServer.open(port)

clients = []
s=Thread.new do
  loop do
    clients << gate.accept
    p clients
  end
end

while msg = STDIN.gets
  p clients
  clients.each do |client|
    if client.closed?
      clients.delete client
    else
      begin
        client.puts msg.upcase
      rescue

      end
    end
  end
end

gate.close

s.join

これだと複数接続できます。接続待ちをするループをThreadにして放置して、 他方でサーバの標準入力待ちを作っています。 接続を切られてしまった場合の処理はどうすればいいのかは よくわかっていません。とりあえず、closed?が返ったり書き込もうとして 例外が返った場合の処理だけしています。 クライアント切っただけではclosed?がtrueにならないのに、 書き込みはできずに例外が返ったりして、よくわかりません。

Rubyでサーバを作ってクライアントにデータを配信 vol.1

これはRubyで作ったソケットサーバに接続してきたクライアントにデータを配信するための勉強上の知見です。

require "socket"

port = if ARGV[0] then ARGV[0] else 'echo' end
gate = TCPServer.open(port)

sock = gate.accept
gate.close

while msg = STDIN.gets
    sock.puts msg.upcase
end
sock.close

サーバを立ち上げる

% ruby multisend00.rb 9999

クライアントはワンライナーで。

ruby -rsocket -e 's=TCPSocket.new("localhost",9999);while a=s.gets;puts a end'

サーバ上で、「abc」と入力してエンターを押すと、 クライアント画面にABCと大文字になって出てくる。 f:id:xibbar:20150814160223p:plain

懐中電灯作った

息子がキャンプに持っていく懐中電灯買って欲しいという。 よし!つくろう。と思って作ったのがこちら。


LED Light - YouTube

スズメッキ線を殆ど使わずにはんだだけで結線しています。 基板は秋月で売っているもので、ブレッドボードのような 配線になっていて、縦と横のホールが大分つながっています。

ただのお遊びです。

ラビックスは14期目に入りました

創業してから13年も経営してしまいました

なんだかあっという間の1年でした。移転して慣れるまで時間がかかりました。 こうして挨拶を書けるのも、 ラビックスを続けようとしてくれている社員とみなさまのお陰です。 一回り以上してしまったので、これからはいかに続けるかと、 いかに安定して成長するかでしょう。

ちょっとずついろいろできることが増えてきました

娘が4歳になったので、ちょっとずつ手がかからなくなってきました。 病気も熱を出した時以外は割りと安定している感じです。 息子は10歳です。もうちょっとで中学生か〜とか思います。早い。 そして、大丈夫か??とか思います。

新しい業務

新しいサービスを開始します。もうちょっとしたらリリースします。 新しいと言っても既存のe-安否に付随させるサービスです。 そっからスタートです。

藤岡が思う復興

福島ですし、復興に関することはあらゆることで耳に入りますし、 社会の一員を担う以上、復興は無視というわけにはいきません。 でも、ボランティア活動をする人がいたり、募金活動をする人もいます。 芸術活動をする人もいます。 原発への反対活動をする人もおそらく当事者は復興の活動の一部だと思っているに違いありません。 私には自分自身が思う復興活動というものがあります。 それは、ビジネスを大きくすることです。 私は復興というものはビジネス以外ありえないと思っています。 経済を中心に循環しない限り寂れるだけだと思っています。 雇用を少しでも生むというのが大切です。 それに微力ながら役に立てればいいと思っています。

最後に

今期もラビックスは新しいビジネスをもって社会に貢献します。 みなさま今後共よろしくお願いします。

去年と同じことを言っていますが、 # 福島市中心部で、家政婦さんをやれる人がいたら教えて下さい。

さくらクラウドとRTX810でVPNを使ってLAN同士を接続する

仕事で必要なので、社内でつなげようと動作を検証していましたが、 やっと動作したので、やり方を報告します。

基本的には サイト間VPN設定 | さくらのクラウド ドキュメント に載っているとおりです。

注意としては、RTX810ではIPsec IDはローカルIPアドレスになります。 記事で言うと、*3で注意書きがあります。

また、PPPoEでプロバイダとつないでいたりすると、グローバルIPアドレスに IP Masqueradeの設定が入っているので、LAN側にNATでIP Secのパケットを 引きこまなければなりません。うちはネットワーク型のPPPoEですので、 記事のとおりの設定+以下の設定を入れました。

nat descriptor masquerade static 1000 13 10.0.0.1 udp 500
nat descriptor masquerade static 1000 14 10.0.0.1 esp
nat descriptor masquerade static 1000 15 10.0.0.1 udp 4500

これはRTX810のグローバルIPアドレスのNAT設定への追記になります。 うちのPPPoEでネットワーク型接続をしているルーターと さくらクラウドVPCとの接続設定のサンプルを載せておきます。 参考までにどうぞ。

ip route default gateway pp 1
ip route 172.16.0.0/16 gateway tunnel 1
vlan port mapping lan1.1 vlan1
vlan port mapping lan1.2 vlan2
vlan port mapping lan1.3 vlan3
vlan port mapping lan1.4 vlan4
lan type lan1 port-based-option=divide-network
ip vlan1 address 10.0.0.1/24
ip vlan1 secure filter in 200099
ip vlan1 secure filter out 200099
ip vlan2 address 198.51.100.124/27
ip vlan2 nat descriptor 1000
ip vlan2 secure filter in 200099
ip vlan2 secure filter out 200099
provider type isdn-network
provider vlan1 name LAN:
provider lan2 name PPPoE/0/3/5/0/0:Provider
pp select 1
 pp name PRV/1/3/5/0/0:Provider
 pp keepalive interval 30 retry-interval=30 count=12
 pppoe use lan2
 pppoe auto disconnect off
 pp auth accept pap chap
 pp auth myname username password
 ppp lcp mru on 1454
 ppp ipcp msext on
 ppp ccp type none
 ip pp secure filter in 200099
 ip pp secure filter out 200099
 ip pp nat descriptor 1000
 pp enable 1
provider set 1 Provider
 provider dns server pp 1 1
 provider select 1
tunnel select 1
 ipsec tunnel 101
  ipsec sa policy 101 1 esp aes-cbc sha-hmac
  ipsec ike always-on 1 on
  ipsec ike encryption 1 aes-cbc
  ipsec ike group 1 modp1024
  ipsec ike hash 1 sha
  ipsec ike keepalive log 1 off
  ipsec ike keepalive use 1 on dpd 15 2
  ipsec ike local address 1 10.0.0.1
  ipsec ike local id 1 10.0.0.1
  ipsec ike pfs 1 on
  ipsec ike pre-shared-key 1 text test12345
  ipsec ike remote address 1 203.0.113.180
  ipsec ike remote id 1 203.0.113.180
  ipsec auto refresh 1 on
 ip tunnel mtu 1280
 ip tunnel tcp mss limit auto
 tunnel enable 1
ip filter 200099 pass * * * * *
nat descriptor type 1000 masquerade
nat descriptor address outer 1000 198.51.100.124
nat descriptor address inner 1000 10.0.0.1-10.0.0.254
nat descriptor masquerade static 1000 13 10.0.0.1 udp 500
nat descriptor masquerade static 1000 14 10.0.0.1 esp
nat descriptor masquerade static 1000 15 10.0.0.1 udp 4500
ipsec auto refresh on
syslog notice on
syslog debug on

手元の設定をかなり削って、IPアドレスやら設定をかなり変更したので、 もしもどこか間違っていたらごめんなさい。

でも、さくらクラウドVPCとRTX810のネットワーク型PPPoEの内側のLANは接続できました。