rubyでsocket


socketを使ったプログラムを書いてみた。
測定用の自動化には、いろいろな仕組みがある。全部、ひとつのプログラムがやっているのが多い気がするが、制御の部分にサーバーを立ててGUI部分がクライアントとしてそれにアクセスしに行っているようなシステムも見受けられる。装置の制御部分は、一つのタスクからのみにした方がconflictが無くて良いと思うので、それをサーバーに任せるというのは理にかなっているように感じる。 そこで、そのようなシステムを組む練習がてら、遅ればせながらsocketというものを使ってみた。rubyでは、socketを簡単に使えるらしい。試しに書いてみたサーバー部がこれ。

require 'socket'
s=TCPServer.new(12344)
Thread.start(s.accept){|cl|
print "%s is accepted\n"%cl.peeraddr
  cl.each{|cmd|
    str=""
    case cmd.strip
    when "status"
      str=(rand(2)>0)?"good":"bad"
    when "color"
      str=["red","green","blue"][rand(3)]
    end
    cl.puts str
  }
  cl.close
print "%s is terminated\n"%cl.peeraddr
} while true

cygwin上で書いていたのだが、ポートは12345はトロイの木馬と勘違いされてだめだった。そして、クライアントはこれ。

s=TCPSocket.open("localhost",12344)
5.times{
  s.write(["status\n","color\n"][rand(2)])
  p s.gets
  sleep 2
}
s.close

とりあえずは動くのだが、いろいろと気に入らない点がある。まず、クライアントからの入力に対して、出力を二行以上にしようとしたら、なぜかうまくいかなかった。print文が働かないように見える。それから、クライアントの接続が切れたことを認識してくれない。これだと、接続がつながって切れる度に、スレッドが増えていくことになってしまう。windows上で動かしているからなのかもしれない。時間ができたらlinux上でいろいろと試してみよう。 他の人が書いたプログラムとかを参考にいろいろと勉強しないといけないようだ。HTMLとかPOPなんかも勉強すると参考になるかな。

2008/12/25追記 接続を切ったときには、Errno::ECONNABORTEDというエラーが起こっているようだ。スレッドはこのエラーで終了してしまうので、どんどんスレッドが増えることはないようだ。気持ちわるいので、rescueとかensureとかでこのエラーが起こったときの対処をすれば、それなりに動いた。

2008/12/25追記 いろいろいじっているうちに、二行以上も受け取れるようになった。おそらく主な原因は、

p s.gets until $_=~/^END/

としていたが、

begin
  p s.gets
end until $_=~/END/

と書き換えることによって、getsが条件判定よりも前に行うようになったからだと思う。untilが後にあるから、後に実行しているような気になっていた。でも、なんか変な気がする。