Ruby の Socket.tcp を知った

Ruby で TCP のクライアントとしてサーバーに接続するには TCPSocket.open(TCPSocket.new)を使うもんだと思ってたんだけど、最近 Socket.tcp というのもあることを知った。

どうやら 1.9.2 で追加されたらしい。10年以上も気づかなかった…。サーバー側の Socket.tcp_server_loop も同じ時に追加されていてこっちは気づいてたんだけどなぁ。

TCPSocket.openSocket.tcp もクライアントとしてサーバーに接続するのでだいたい同じなんだけど、Socket.tcp の方は connect_timeout というキーワード引数で接続タイムアウト時間を指定できる(2.0.0 から)。 なお、2.7 から resolv_timeout というキーワード引数でホスト名解決のタイムアウト時間を指定できるようにもなっている…と思いきや、3.0 では無効になってた。短い命だった。

返すオブジェクトが TCPSocketSocket かの違いはある。けど、TCPSocket の方に addr, peeraddr というメソッドがある程度の違い。

TCPSocket.instance_methods - Socket.instance_methods
 #=> [:addr, :peeraddr]

それに addr, peeraddr と同じ役割のメソッドは Socket の方にも local_address, remote_address として用意されている。

s = TCPSocket.open("google.com", 80)
s.addr
 #=> ["AF_INET6", 51432, "2405:6582:6260:1b00:f7c9:81c:93f6:b1bd", "2405:6582:6260:1b00:f7c9:81c:93f6:b1bd"]
s.peeraddr
 #=> ["AF_INET6", 80, "2404:6800:4004:818::200e", "2404:6800:4004:818::200e"]

s = Socket.tcp("google.com", 80)
s.local_address
 #=> #<Addrinfo: [2405:6582:6260:1b00:f7c9:81c:93f6:b1bd]:51444 TCP>
s.remote_address
 #=> #<Addrinfo: [2404:6800:4004:81d::200e]:80 TCP>

local_address, remote_address の方は配列じゃなくてちゃんとオブジェクトを返すので良さそう。


と、ここまで書いて TCPSocket のソースを読んでみたら、TCPSocket.open の方にも connect_timeout というキーワード引数が増えていた。3.0 で追加されたらしい。

というわけで、まあどっちでも好きな方を使えばいいんだけど、個人的には Socket.tcp の方が良さそうな気がしてるので、今後は Socket.tcp を使おうと思う。