RubyでTCP_FASTOPENを使う

サーバ側

setsockoptにTCP_FASTOPENを渡せば良い。
TCP_FASTOPENは、trunkのr42865以降Socket::TCP_FASTOPENとして定義されている。

require "socket"

TCP_FASTOPEN = Socket::TCP_FASTOPEN || 23

serv = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM)
serv.setsockopt(Socket::SOL_TCP, TCP_FASTOPEN, 5)
addrinfo = Addrinfo.new(Socket.sockaddr_in(8888, "localhost"))
serv.bind(addrinfo)
serv.listen(1)

loop do
  socket, addrinfo = serv.accept
  p socket, addrinfo
  p socket.gets
end

クライアント側

RubyのSocketライブラリでは明示的にsendto(2)を呼ぶ事はできないが、
Socket#send(BasicSocket#send)の第3引数にソケットアドレス構造体をpackした文字列を渡す事で内部ではsendto(2)が使われる。
(詳しくはext/socket/init.cのrsock_bsock_send()を参照)
Server.tcpなどでTCPのソケットを作成した場合は既にconnectされてしまっているのでErrno::EISCONNが返ってくる。
そのためSocket.newから行う必要がある。
今のところtrunkでもMSG_FASTOPENは定数として定義されていない。

require "socket"

MSG_FASTOPEN = 0x20000000

socket = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM)
socket.send("foo\r\n", MSG_FASTOPEN, Socket.sockaddr_in(8888, "localhost"))