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

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