RubyのSocket.tcp_server_loopでechoサーバを作り、その通信を ngrepで確認してみた

Rubyで echo サーバを作ろうと思い調べたところ、 TCPServer クラスがありました。
class TCPServer (Ruby 3.3 リファレンスマニュアル)

リファレンスマニュアルには echo サーバの実装が記載されていました。

 
もう少し調べてみたところ、RubyKaigi 2009 の資料「ソケットライブラリの改善」がありました。
ソケットライブラリの改善 - 日本Ruby会議2009

この資料を読んだところ、TCPServer を使うよりは Socket.tcp_server_loop を使うほうが良さそうでした。
Socket.tcp_server_loop (Ruby 3.3 リファレンスマニュアル)

そこで、 Socket.tcp_server_loop で echo サーバを作り、その通信を ngrep で確認してみたので、メモを残します。

 
目次

 

環境

 

echo サーバの実装

Socket.tcp_server_loop を使って echo サーバを実装します。ポートは 12345 で待ち受けます。

なお、ブロックに渡されてくるソケットオブジェクトのクラスやメッセージの中身を確認するようなコードも入れています。

# tcp_echo_server.rb

require 'socket'

PORT = '12345'

Socket.tcp_server_loop(PORT) do |sock, addr_info|
  p sock.class #=> Socket
  message = sock.recv 1000
  p message # => "hello\n"
  p message.class #=> String

  sock.sendmsg message
ensure
  sock.close
end

 

ngrepをインストールする

echoサーバの通信内容を確認するため、今回はお手軽な ngrep を使います。

 
WSL2のUbuntuでは ngrep が未インストールだったため、インストールしておきます。

$ sudo apt install ngrep

 

ngrepでechoサーバの通信内容を確認する

まず、1つ目のターミナルで echo サーバを起動します。

$ ruby tcp_echo_server.rb

 
続いて、2つ目のターミナルを起動します。

ngrep で通信内容をキャプチャするために、ネットワークインタフェースを ip コマンドで確認しました。

$ ip -br -4 address
lo               UNKNOWN        127.0.0.1/8
eth0             UP             ***.***.***.***/*** 
br-***           DOWN           ***.***.***.***/*** 
docker0          DOWN           ***.***.***.***/***

 
今回の場合は lo を使えば良さそうなので、 ngrep を実行します。

$ sudo ngrep -x -q -d lo '' 'port 12345'

[sudo] user のパスワード: 
interface: lo (127.0.0.0/255.0.0.0)
filter: ( port 12345 ) and ((ip || ip6) || (vlan && (ip || ip6)))

 
最後に、3つ目のターミナルにて、 nc コマンドで echo サーバへメッセージ hello を投げます。すると、 hello という返信が返ってきました。

$ echo hello |  nc localhost 12345
hello

 
1つ目のターミナルを確認すると、いくつかの値が出力されていました。

Socket
"hello\n"
String

 
2つ目のターミナルでは、 hello メッセージのやり取りが出力されていました。

T 127.0.0.1:54122 -> 127.0.0.1:12345 [AP] #4
  68 65 6c 6c 6f 0a                                     hello.          

T 127.0.0.1:12345 -> 127.0.0.1:54122 [AP] #6
  68 65 6c 6c 6f 0a                                     hello.  

 
以上で、 echo サーバとの通信を ngrep で確認することができました。

 

ソースコード

GitHubに上げました。
https://github.com/thinkAmi-sandbox/tcp_servers_by_ruby

今回のプルリクはこちら。
https://github.com/thinkAmi-sandbox/tcp_servers_by_ruby/pull/1