TCPソケットとUDPソケットが同一のポートにbindした場合、クライアントからのメッセージはどちらが受信するのか?


試してみた。
結論は最後のまとめに書いてある。

Serverを立てる

require 'socket'

### tcp1
tcp_socket = Socket.new(:INET, :STREAM)
tcp_socket.bind Socket.sockaddr_in(9002, '<any>')
tcp_socket.listen 5

### tcp2 (エラーでて作れなかった)
tcp_socket = Socket.new(:INET, :STREAM)
tcp_socket.bind Socket.sockaddr_in(9002, '<any>')
tcp_socket.listen 5
#=> Errno::EADDRINUSE: Address already in use - bind(2) for 0.0.0.0:9002

### udp1
udp_socket = Socket.new(:INET, :DGRAM)
udp_socket.bind Socket.sockaddr_in(9002, '<any>')

### udp2 (エラーでて作れなかった)
udp_socket2 = Socket.new(:INET, :DGRAM)
udp_socket2.bind Socket.sockaddr_in(9002, '<any>')
#=> Errno::EADDRINUSE: Address already in use - bind(2) for 0.0.0.0:9002


loop do
  res = IO.select([tcp_socket, udp_socket])
  res.first.each do |sock|
    case sock
    when udp_socket
      p '### data received in udp_socket'
      p sock.recvfrom(1024)
    when tcp_socket
      p '### data received in tcp_socket'
      client, from = sock.accept
      data = client.recv(1024)
      p data
      client.puts 'OK'
      client.close
    end
  end
end

Clientからメッセージを送信する


require 'socket'


Socket.open(:INET, :DGRAM) do |sock|
  addr = Socket.sockaddr_in(9002, '127.0.0.1')
  sock.send('hello udp message', 0, addr)
end

Socket.open(:INET, :STREAM) do |sock|
  addr = Socket.sockaddr_in(9002, '127.0.0.1')
  sock.connect addr
  sock.write 'hello tcp message'
  p sock.gets
end

Server側のstdoutは、、、

"### data received in tcp_socket"
"hello tcp message"


"### data received in udp_socket"
["hello udp message", #<Addrinfo: 127.0.0.1:60734 UDP>]

まとめ

  • 1つのポートにバインドできるのは、tcpソケット,udpソケットのそれぞれで最高1つまで。
  • tcpソケットとudpソケットの両方が同一ポートにバインドされている場合、
    • tcpクライアントからのメッセージはtcpソケットが受け取る。
    • udpクライアントからのメッセージはudpソケットが受け取る。

Ref