Socket

ソケットそのものに対するシステムコールレベルのアクセスを提供 するクラス。Perlのソケットに対するアクセスと同レベルの機能を 提供してます。このクラスではソケットアドレスは pack された文字列で指定します (ソケットアドレス構造体を pack した文字列を参照)。

一般的なソケットプログラミングはより高レベルの TCPSocketクラスや TCPServerクラスを用い て行われることが多く、このクラスはあまり用いられません。

スーパークラス:

クラスメソッド:

Socket.open(domain, type, protocol)
Socket.new(domain, type, protocol)

新しいソケットを生成します。domaintypeprotocol はインクルードファイルにある定数で指定しま す。ほとんどの定数は Socket::AF_INET のように Socket クラスの定数として定義されています。domaintype に関しては、"AF_INET", "SOCK_STREAM" のように文字列でも指定できますが、文 字列ですべての機能を指定できる保証はありません。

例えば、IPv4 の TCP ソケットは以下のように生成されます。

s = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)

なお、socket(2) の domain 引数において AF_ と PF_ のどちらの定数を使用するかについては混乱がありますが、 Stevens の「UNIX ネットワークプログラミング第2版 Vol.1」4.2節に述べられているように、 現実的にはどちらでも問題なく、また、既存のコーディング習慣として AF_ が用いられることが多いため、 ここでは AF_ を使用しています。

Socket.for_fd(fd)

ファイルディスクリプタ fd に対する新しいソケットを生成します。

ruby 1.7 feature: このメソッドは BasicSocket に移動しました。

Socket.getaddrinfo(nodename, servname[, family[, socktype[, protocol[, flags]]]])

RFC 2553で定義された getaddrinfo()の機能を提供するクラスメソッド。この関数は gethostbyname()getservbyname()の代わりとして用意されており、 IPのバージョンに依存しないプログラムを書くための標準的なAPIです。

アドレス情報の配列を返します。アドレス情報とは7つの要素からなる次の 形の配列です。

  • 第0要素 - アドレスファミリー(String)。
  • 第1要素 - ポート番号(Integer)。
  • 第2要素 - ホスト名(String)。
  • 第3要素 - アドレス(String)。
  • 第4要素 - アドレスファミリーに対応するInteger。
  • 第5要素 - ソケットタイプに対応するInteger。
  • 第6要素 - プロトコルに対応するInteger。

必須引数の意味は以下の通りです。

残りの引数は省略可能です。

  • family - アドレスファミリー。 Socket::AF_INET など、 アドレスファミリーにある定数を指定します。
  • socktype - ソケットタイプ。 Socket::SOCK_STREAM など、 ソケットタイプにある定数を指定します。
  • protocol - プロトコル。 Socket::IPPROTO_IP など、 プロトコルにある定数を指定します。
  • flags - getaddrinfo(3)の第3引数に指定するaddrinfo構造体の ai_flags メンバに相当するFixnum。 Socket::AI_PASSIVESocket::AI_CANONNAMESocket::AI_NUMERICHOST が用意されている場合があります。

引数に指定できる定数の意味については getaddrinfo(3) を参照して下さい。

例: *1

p Socket.getaddrinfo(Socket.gethostname, "ftp")
#=> [["AF_INET", 21, "helium.ruby-lang.org", "210.251.121.214", 2, 1, 6]]

pp Socket.getaddrinfo(Socket.gethostname, nil)
#=> [["AF_INET", 0, "helium.ruby-lang.org", "210.251.121.214", 2, 1, 6],
#    ["AF_INET", 0, "helium.ruby-lang.org", "210.251.121.214", 2, 2, 17],
#    ["AF_INET", 0, "helium.ruby-lang.org", "210.251.121.214", 2, 3, 0]]
Socket.getnameinfo(sa[, flags])

RFC 2553 で定義されたgetnameinfo() の機能を提供するク ラスメソッド。 gethostbyaddr()getservbyport() の代 わりとして用意されています。IPのバージョンに依存しないプログラムを 書くための標準的なAPIです。

配列を返し、その要素はアドレスとポートを表す文字列です。

引数 sa には文字列か配列を与えます。文字列の場合は sockaddr 構造体 のパック文字列を与えます。具体的には getsockname の値が利用できます。配列を与える場合には、要素が3つの場合と4つの場合 があります。

  • 要素が3つの場合:

    [アドレスファミリー, サービス, ホスト]
    
  • 要素が4つの場合:

    [アドレスファミリー, サービス, 任意, アドレスを表す文字列]
    

アドレスファミリーには Socket::AF_INET 等の定数の他に文字列 で "AF_INET" もしくは "AF_INET6" もしくは nil が 指定できます。ただしIPv6が使えないようにコンパイルされている場合は "AF_INET6" は無効な指定となります。アドレスファミリーに nil を指定することは Socket::AF_UNSPEC を指定すること と等価です。

サービス、ホストの指定に関しては サービス指定形式ホスト指定形式を参照してください。

要素が3つの場合でも、ホストにはアドレスを指定できますが、要素が4つ の場合には、最後の要素を名前解決しないことが保証されます。*2

省略可能な第2引数 flags には getnameinfo(3) の第7番目の引数に指定する flags に相当する Fixnum を与えます。

引数flagsを構成するための定数として Socket::NI_MAXHOSTSocket::NI_MAXSERVSocket::NI_NOFQDNSocket::NI_NUMERICHOSTSocket::NI_NAMEREQDSocket::NI_NUMERICSERVSocket::NI_DGRAM が用意されている場合があります。

これらの定数の意味については getnameinfo(3)を参照 して下さい。

例:

Socket.getnameinfo(Socket.sockaddr_in('21','127.0.0.1'))
#=> ["localhost", "ftp"]

Socket.getnameinfo([nil, 21,'127.0.0.1'])
#=> ["localhost", "ftp"]
Socket.gethostbyaddr(host[, type])

sockaddr 構造体をパックした文字列からホスト情報を返します。 ホスト情報の構造は Socket.gethostbynameと同じです。 type には、アドレスタイプ(デフォルトは Socket::AF_INET)を指定します。

Socket.gethostbyname(host)

ホスト名またはIPアドレス(指定方法に関しては ホスト指定形式を参照) からホストの情報を返します。 ホスト情報は以下の 4 要素の配列で表現されています。

  • ホスト名
  • ホストの別名の配列
  • ホストのアドレスタイプ (整数定数)
  • ホストのアドレス

ホストのアドレスはpackされた 文字列で、unpack("CCCC")で分解できます。

例:
irb(main):009:0> Socket.gethostbyname("210.251.121.214")
["helium.ruby-lang.org", ["helium"], 2, "\322\373y\326"]

ruby 1.8.1 feature

第四要素のホストのアドレスは、各アドレスタイプに対応する C のアドレス構造体を pack した文字列として表現されています。 例えばアドレスタイプが AF_INET (定数 2) ならば Socket.unpack_sockaddr_in で unpack できます。

例:
irb(main):009:0> Socket.gethostbyname("210.251.121.214")
["210.251.121.214", [], 2, "\002\000\000\000\322\373y\326\000\000\000\000\000\000\000\000"]

irb(main):009:0> Socket.unpack_sockaddr_in(Socket.gethostbyname("210.251.121.214")[3])[1]
"210.251.121.214"

ruby 1.8.2 feature

ホストのアドレスはpackされた 文字列で、unpack("CCCC")で分解できます。

例:
irb(main):009:0> Socket.gethostbyname("210.251.121.214")
["210.251.121.214", [], 2, "\322\373y\326"]
Socket.gethostname

システムの標準のホスト名を取得します。

ホストの別名やアドレスなど他の情報を得るには Socket.getaddrinfo を使ってください。 ただし、これは不可能な場合もあります。

p Socket.gethostname   #=> "helium.ruby-lang.org"
Socket.getservbyname(service[, proto])

service, protoに対応するポート番号を返 します。protoの省略値は"tcp"です。

p Socket.getservbyname("echo")
=> 7
p Socket.getservbyname("shell", "tcp")
=> 514
p Socket.getservbyname("syslog", "udp")
=> 514
Socket.sockaddr_in(port, host) (ruby 1.7 feature)
Socket.pack_sockaddr_in(port, host) (ruby 1.7 feature)

指定したアドレスをソケットアドレス構造体を pack した文字列 で返します。port は、ポート番号を表す Fixnum あるいは、ポート 番号、サービス名を表す文字列です。

require 'socket'
p Socket.sockaddr_in("echo", "localhost")
=> "\002\000\000\a\177\000\000\001\000\000\000\000\000\000\000\000"
p Socket.sockaddr_in("echo", "::1")
=> "\n\000\000\a\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000"
Socket.sockaddr_un(path) (ruby 1.7 feature)
Socket.pack_sockaddr_un(path) (ruby 1.7 feature)

指定したアドレスをソケットアドレス構造体を pack した文字列 で返します。

require 'socket'
p Socket.sockaddr_un("/tmp/.X11-unix/X0")
=> "\001\000/tmp/.X11-unix/X0\000...."
Socket.pair(domain, type, protocol)
Socket.socketpair(domain, type, protocol)

相互に結合されたソケットのペアを含む2要素の配列を返します。 引数の指定はSocket.openと同じです。

Socket.unpack_sockaddr_in(sockaddr) (ruby 1.7 feature)

ソケットアドレス構造体を pack した文字列を unpack したアドレスを返します。返される値は [port, ipaddr] の配列です。

require 'socket'
p Socket.unpack_sockaddr_in(Socket.sockaddr_in("echo", "localhost"))
=> [7, "127.0.0.1"]
p Socket.unpack_sockaddr_in(Socket.sockaddr_in("echo", "::1"))
=> [7, "::1"]
Socket.unpack_sockaddr_un(sockaddr) (ruby 1.7 feature)

ソケットアドレス構造体を pack した文字列を unpack したソケットパス名をを返します。

require 'socket'
p Socket.unpack_sockaddr_un(Socket.sockaddr_un("/tmp/.X11-unix/X0"))
=> "/tmp/.X11-unix/X0"

メソッド:

accept

新しい接続を受け付けて、新しい接続に対するソケットと接続元のアドレスの 2つからなる配列を返します。accept(2)を参照。

たとえば IPv4 の TCP サーバソケットを生成し、accept でクライアントからの接続を受け付けるには以下のようにします。

serv = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
sockaddr = Socket.sockaddr_in(8080, "0.0.0.0")
serv.bind(sockaddr)
serv.listen(5)
sock, sockaddr = serv.accept
accept_nonblock

ruby 1.8.5 feature

ソケットをノンブロッキングモードに設定した後、 accept(2)を呼び出します。

引数、返り値は accept と同じです。

accept(2)がエラーになった場合、 EAGAIN, EINTR を含め例外 Errno::EXXX が発生します。

bind(my_sockaddr)

ソケットをmy_sockaddrに結合します。bind(2) と同じ働きをします。my_sockaddrソケットアドレス構造体を pack した文字列 です。

0 を返します。

connect(server_sockaddr)

connect(2)と同じ働きをします。server_sockaddr は、 ソケットアドレス構造体を pack した文字列 です。

0 を返します。

たとえば IPv4 の TCP ソケットを生成し、connect で www.ruby-lang.org:80 に接続するには以下のようにします。

s = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
sockaddr = Socket.sockaddr_in(80, "www.ruby-lang.org")
s.connect(sockaddr)
s.write "GET / HTTP/1.0\r\n\r\n"
print s.read
connect_nonblock(server_sockaddr)

ruby 1.8.5 feature

ソケットをノンブロッキングモードに設定した後、 connect(2)を呼び出します。

引数、返り値は connect と同じです。

connect(2)がエラーになった場合、 EINPROGRESS を含め例外 Errno::EXXX が発生します。

listen(backlog)

listen(2)と同じ働きをします。

0 を返します。

recvfrom(maxlen[, flags])

recvと同様にソケットからデータを受け取りますが、 戻り値は文字列と相手ソケットのアドレスのペアです。引数につい てはrecvと同様です。

s1 = Socket.new(Socket::AF_INET, Socket::SOCK_DGRAM, 0)
s2 = Socket.new(Socket::AF_INET, Socket::SOCK_DGRAM, 0)
s1.bind(Socket.sockaddr_in(0, "0.0.0.0"))
s2.send("foo", 0, s1.getsockname)
mesg, sockaddr = s1.recvfrom(10)
p mesg                                    #=> "foo"
p sockaddr                                #=> "\002\000\200r\177\000\000\001\000\000\000\000\000\000\000\000"
p Socket.unpack_sockaddr_in(sockaddr)     #=> [32882, "127.0.0.1"]
recvfrom_nonblock(maxlen[, flags])

ruby 1.8.5 feature

ソケットをノンブロッキングモードに設定した後、 recvfrom(2)を呼び出します。

引数、返り値は recvfrom と同じです。

recvfrom(2)がエラーになった場合、 EAGAIN, EINTR を含め例外 Errno::EXXX が発生します。

sysaccept (ruby 1.7 feature)

接続したクライアントのファイル記述子とアドレスのペアを返すことを除 けば accept と同じです。


*1 Linuxではservnameにポート番号(0や21や"0"や"21"など)は getaddrinfo: Servname not supported for ai_socktype (SocketError)に なって使えないようです。
*24つの 場合の3番目の引数ってなんだか変なインタフェースですね。4番目の引数 が nil の場合は要素3つと同じ扱いになるんですね。どういうわけでこう なってるのかがよくわかりません。ホスト指定は常に3番目の要素にして [アドレスファミリー, サービス, ホスト, フラグ] として4番目の要素で 名前解決うんぬんを指定するんじゃダメだったんでしょうかね?-あらい 2002-01-01



rubyist ML