添付ライブラリ: ネットワーク

TCP Server Class

これでTCP用の簡易アプリケーションサーバーを構築することが出来る。

require "socket"
server = TCPServer.new 10080
while(true) do
  client = server.accept
  puts client.inspect
  client.puts "<p1>Hello Server</p1>"
  client.close
end

chromeだと「無効な応答が表示されました」になってしまうが、Edgeだとちゃんと正常に表示がされる。

TCP Socket Class

クライアント側も簡単に作ることが出来る。

require "socket"

socket = TCPSocket.new "localhost", 10080
while line = socket.gets
  sleep 1
  puts line
end

UDP Socket Class

UDPはクライアント側、サーバー側の区別なくTCP Scoket Classを用いる。

まずはクライアント側

require "socket"

MAX_PACKET = 1024
socket = UDPSocket.new
socket.bind("0.0.0.0",10000)
print socket.recv(MAX_PACKET) # "Hello UDP"

次にサーバー側

require "socket"
socket = UDPSocket.new

socket.send "Hello UDP\n", 0, "localhost", 10000
socket.close

プロセス間通信

UNIX系のOSでのみサポートしている、同じインスタンス内部での複数のプロセス同士の通信がサポートされている。 使い方はTCPサーバーとあまり変わらない。実際C言語ではTCP用のクラスをそのまま用いてやるらしい。

UnixServer Class

require "socket"
socket_name = "test_socket"

server = UNIXServer.new socket_name
loop {
  client = server.accept
  client.puts "Hello Unix Server"
  client.close
}

UnixSocket Class

ソケット名を指定するだけで受信できてしまうので簡単。

require "socket"

socket = UNIXSocket.new "test_socket"
print socket.gets "Hello Unix Server"

URI

URI.parse(str)またはURI(str)スキーマ、ホスト名、ポート番号、パスなどに情報を分割したオブジェクトを渡してくれる。

require "uri"

uri = URI("https://aoyama-portal.aoyama.ac.jp/aogaku_auth/jsp/AUTH01.jsp?TYPE=167772161&REALMOID=06-2a27689c-587a-42e0-834c-7a6751c24219")

p uri.scheme "https"
p uri.host   "aoyama-portal.aoyama.ac.jp"
p uri.port   "433"
p uri.path   "/aogaku_auth/jsp/AUTH01.jsp"
p uri.query  "TYPE=167772161&REALMOID=06-2a27689c-587a-42e0-834c....." 

URI.parseまたはURIRFCの規約に従って厳密な分割がされるので、RFCで使えないとされる文字が使われていればパースされない。

require "uri"

uri = URI("https://identity.cisco_lern.com/api/v1/idp-discovery/discovery")
# /home/pyons/.rbenv/versions/2.1.0/lib/ruby/2.1.0/uri/generic.rb:214:in `initialize': the scheme https does not accept registry part: identity.cisco_lern.com (or bad hostname?) (URI::InvalidURIError)

URIパーサーで返ってくるオブジェクトを、単なる配列にしたものがsplitメソッドである。どの順番で何の要素が入るのか決まっているので、nilが入る場所もある。

require "uri"

uri = URI.split("https://identity.cisco.com/api/v1/idp-discovery/discovery")
p uri
# ["https", nil, "identity.cisco.com", nil, nil, "/api/v1/idp-discovery/discovery", nil, nil, nil]
uri = URI.split("https://www.swinburne.edu.au/")
p uri
# ["https", nil, "www.swinburne.edu.au", nil, nil, "/", nil, nil, nil]
uri = URI.split("https://aguinfo.jm.aoyama.ac.jp/AGUInfo/message_list.aspx")
p uri
# ["https", nil, "aguinfo.jm.aoyama.ac.jp", nil, nil, "/AGUInfo/message_list.aspx", nil, nil, nil]

ASCII以外の文字をURIに使用するときは%XXという16進数表記にすることがRFCで定められている。この変換に`URI.encode_www_form_componentというクラスメソッドを用いる。逆に16進数からのデコードにはdecode_www_form_componentを用いる。

HTTP通信

HTTP通信をサポートする専用のライブラリが存在する。startgetstopというインスタンスメソッドで操作したり、ブロックを渡して通信させたり、もしくはクラスメソッドで直接getを指定することもできる。

(教科書のサンプルコード通りやってみてもMoved Permanentlyばかり却って来てしまう。HTTPSの設定かSSLの設定をしないといけないということなのかもしれないが、これに関して一回パス)

start, get, stop方式

準備中

ブロック方式

準備中

クラスメソッドを利用する方式

準備中

より高度なヘッダ設定

ここまではGETメソッドだけだったが、post, update, またはBasic認証用のヘッダをリクエストに付与することもできる。

postやupdateを利用する場合は通常のNet::HTTPに加えて新たにリクエストパラメータを設定するクラスであるNet::HTTP::Post.newNet::HTTP::Post.newを用いる。またレスポンスの中身は不要で、レスポンスに付与されるヘッダの情報だけが欲しい場合Net::HTTP::Head.newという変わったリクエストを送ることが出来る。

Basic認証用ヘッダは以下のように作成する。

require "net/http"

http = Net::HTTP.new("aguweb.herokuapp.com")
req = Net::HTTP::Get.new("/")
req.basic_auth("*****","*****")
res = http.request(req)
p res.body # "<html><body>You are being <a href=\"http://aguweb.herokuapp.com/users/sign_in\">redirected</a>.</body></html>"