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と大文字になって出てくる。
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.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して、接続待ちと書き出しを別々のプロセスでやっているという 意味のないプログラムです。