names=tcp_server_loop
visibility=public
kind=defined

--- tcp_server_loop(port){|sock,addr| ...} -> ()
--- tcp_server_loop(host, port){|sock,addr| ...} -> ()
TCP/IP で host:port で待ち受けるサーバ側のソケットを作成し、
新しい接続を受け入れるごとにブロックを呼び出します。

ブロックには新しい接続を表すソケットオブジェクトと、
クライアントアドレスを表す [[c:Addrinfo]] オブジェクトが渡されます。

ブロックの実行が終わってもソケットは close されません。
アプリケーション側が明示的に close する必要があります。

このメソッドはブロックを逐次的に呼び出します。
つまりブロックからリターンするまで次のコネクションを受け入れません。
そのため、同時に複数のクライアントと通信したい場合は
スレッドのような並列機構を使う必要があります。

サーバのソケットアドレスを決めるために
[[m:Addrinfo.getaddrinfo]] が用いられることに注意してください。
[[m:Addrinfo.getaddrinfo]] は複数のアドレスを返す(IPv4 と IPv6 など)
場合があり、その場合その全てが用いられます。つまり IPv4 と IPv6 の
両方を待ち受けます。getaddrinfo が 0 個のアドレスを返す場合はエラー
になります。1つ以上を返した場合にそれが用いられます。

  # 逐次的な echo サーバ
  # 一度に一つのクライアントした取り扱えない
  Socket.tcp_server_loop(16807) {|sock, client_addrinfo|
    begin
      IO.copy_stream(sock, sock)
    ensure
      sock.close
    end
  }
  
  # スレッドを使った echo サーバ
  # 同時に複数のクライアントを取り扱える
  # 以下の例だと接続制限がない(つまり接続過剰になりえる)ことに注意
  Socket.tcp_server_loop(16807) {|sock, client_addrinfo|
    Thread.new {
      begin
        IO.copy_stream(sock, sock)
      ensure
        sock.close
      end
    }
  }

内部的には [[m:Socket.tcp_server_sockets]] で
生成したソケットを [[m:Socket.accept_loop]] で処理しています。

@param host 割り当てるホスト名
@param port 割り当てるポート番号
@see [[m:Socket.tcp_server_sockets]], [[m:Socket.accept_loop]]

