せかいや

いまいるここを、おもしろく http://sekai-in-the-box.appspot.com/

【Ruby】ソケットプログラミング

 
この本を読んでるよー。

プログラミング言語 Ruby

プログラミング言語 Ruby

ソケットプログラミングにチャレンジ、、!


 

エラー1 ホスト名の指定

TCPServerにてconnectエラーが発生。

tcp_client.rb:3:in `initialize': No connection could be made because the target machine actively refused it. - connect(2) (Errno::ECONNREFUSED)

ポートは開いている。(netstat -anコマンド)

TCP [::]:2000 [::]:0 LISTENING

■原因
ホスト名を指定してリスンしないと上記エラーが発生する。
ファイアウォール起因かな?

TCPServer.openはホスト名を指定する必要がある。
UDPSocket.new.bind(nil, port)はlocalhostでリスンされる(※1)
 

server = TCPServer.open(2000)

server = TCPServer.open("localhost", 2000)

これでエラーが解決した。
 

※1

ds = UDPSocket.new
ds.bind(nil, port)
ruby C\udp_server.rb 2000
>netstat -an
UDP    127.0.0.1:2000     *:*

 

エラー2 Firewallでポートを許可する

TCPSocket.readpartialメソッドを使用して、
サーバーからの応答を読み出そうとしたら以下のエラーが発生。

telnet_client.rb:26:in `readpartial': An established connection was aborted by the software in your host machine. (Errno::ECONNABORTED)

 
■原因
ファイアーウォールで通せんぼされていた。
使用するポートを2000番⇒80番に変えるとエラーは解消された。

server = TCPServer.open("localhost", 80)

 
 
 
 

一回きりのサーバークライアント間通信を行う

TCPソケット

■サーバー

require 'socket'
#指定しないと任意ホストでリスンされる
server = TCPServer.open("localhost", 2000)
loop {
  client = server.accept
  client.puts("hello")
  client.close
}

 
■クライアント

require 'socket'
host, port = ARGV
TCPSocket.open(host, port) do |s|
  while line = s.gets
    puts line.chop
  end
end

■実行結果

hello


UDPソケット

■サーバー

require 'socket'
port = ARGV[0]
ds = UDPSocket.new
ds.bind(nil, port)   #<= 127.0.0.1でリスンされる
loop do
  request, address = ds.recvfrom(1024)
  response = request.upcase
  clientaddr = address[3]
  clientname = address[2]
  clientport = address[1]
  ds.send(response, 0, clientaddr, clientport)
  p address
end

 
■クライアント

require 'socket'
host, port, request = ARGV
ds = UDPSocket.new
ds.connect(host, port)
ds.send(request, 0)
response, address = ds.recvfrom(1024)
puts response

■実行結果

["AF_INET", 55421, "127.0.0.1", "127.0.0.1"]

クライアントからのリクエストを複数回受け付けるサーバー通信は次回!
 ⇒こちら http://sekai.hateblo.jp/entry/2013/10/22/193326