Ruby-ソケットプログラミング
Rubyは、ネットワークサービスへの2つのレベルのアクセスを提供します。低レベルでは、基盤となるオペレーティングシステムの基本的なソケットサポートにアクセスできます。これにより、コネクション型プロトコルとコネクションレス型プロトコルの両方のクライアントとサーバーを実装できます。
Rubyには、FTP、HTTPなどの特定のアプリケーションレベルのネットワークプロトコルへの高レベルのアクセスを提供するライブラリもあります。
この章では、ネットワーキング-ソケットプログラミングの最も有名な概念について理解します。
ソケットとは何ですか?
ソケットは、双方向通信チャネルのエンドポイントです。ソケットは、プロセス内、同じマシン上のプロセス間、または異なる大陸のプロセス間で通信できます。
ソケットは、Unixドメインソケット、TCP、UDPなどのさまざまなチャネルタイプで実装できます。ソケットは共通トランスポートだけでなく、残りの部分を処理するための汎用インタフェースを処理するための特定のクラスを提供します。
ソケットには独自の語彙があります-
シニア番号 | 用語と説明 |
---|---|
1 | domain トランスポートメカニズムとして使用されるプロトコルのファミリー。これらの値は、PF_INET、PF_UNIX、PF_X25などの定数です。 |
2 | type 2つのエンドポイント間の通信のタイプ。通常、コネクション型プロトコルの場合はSOCK_STREAM、コネクションレス型プロトコルの場合はSOCK_DGRAMです。 |
3 | protocol 通常はゼロです。これは、ドメインおよびタイプ内のプロトコルのバリアントを識別するために使用できます。 |
4 | hostname ネットワークインターフェースの識別子- 文字列。ホスト名、ドット付きクワッドアドレス、またはコロン(場合によってはドット)表記のIPV6アドレスにすることができます。 INADDR_BROADCASTアドレスを指定する文字列「<broadcast>」。 INADDR_ANYを指定する長さゼロの文字列、または ホストバイト順のバイナリアドレスとして解釈される整数。 |
5 | port 各サーバーは、1つ以上のポートで呼び出すクライアントをリッスンします。ポートは、Fixnumポート番号、ポート番号を含む文字列、またはサービスの名前です。 |
シンプルなクライアント
ここでは、特定のポートと特定のホストへの接続を開く非常に単純なクライアントプログラムを作成します。RubyクラスTCPSocketそのようなソケットを開くためのopen機能を提供します。
ザ・ TCPSocket.open(hosname, port )TCP接続が開き、ホスト名のポートを。
ソケットを開いたら、他のIOオブジェクトと同じようにソケットから読み取ることができます。完了したら、ファイルを閉じるのと同じように、忘れずに閉じてください。
次のコードは、特定のホストとポートに接続し、ソケットから使用可能なデータを読み取り、終了する非常に単純なクライアントです。
require 'socket' # Sockets are in standard library
hostname = 'localhost'
port = 2000
s = TCPSocket.open(hostname, port)
while line = s.gets # Read lines from the socket
puts line.chop # And print with platform line terminator
end
s.close # Close the socket when done
シンプルなサーバー
インターネットサーバーを作成するには、 TCPServerクラス。TCPServerオブジェクトは、TCPSocketオブジェクトのファクトリです。
今すぐ電話 TCPServer.open(hostname, portサービスのポートを指定して作成する関数TCPServer オブジェクト。
次に、返されたTCPServerオブジェクトのacceptメソッドを呼び出します。このメソッドは、クライアントが指定したポートに接続するまで待機してから、そのクライアントへの接続を表すTCPSocketオブジェクトを返します。
require 'socket' # Get sockets from stdlib
server = TCPServer.open(2000) # Socket to listen on port 2000
loop { # Servers run forever
client = server.accept # Wait for a client to connect
client.puts(Time.now.ctime) # Send the time to the client
client.puts "Closing the connection. Bye!"
client.close # Disconnect from the client
}
ここで、このサーバーをバックグラウンドで実行してから、上記のクライアントを実行して結果を確認します。
マルチクライアントTCPサーバー
インターネット上のほとんどのサーバーは、一度に多数のクライアントを処理するように設計されています。
RubyのThreadクラスを使用すると、マルチスレッドserver.oneを簡単に作成できます。このサーバーは、要求を受け入れ、すぐに新しい実行スレッドを作成して接続を処理し、メインプログラムがさらに接続を待機できるようにします。
require 'socket' # Get sockets from stdlib
server = TCPServer.open(2000) # Socket to listen on port 2000
loop { # Servers run forever
Thread.start(server.accept) do |client|
client.puts(Time.now.ctime) # Send the time to the client
client.puts "Closing the connection. Bye!"
client.close # Disconnect from the client
end
}
この例では、永続的なループがあり、server.acceptが応答すると、新しいスレッドが作成され、スレッドに渡された接続オブジェクトを使用して、受け入れられたばかりの接続を処理するためにすぐに開始されます。ただし、メインプログラムはすぐにループバックし、新しい接続を待ちます。
このようにRubyスレッドを使用すると、コードが移植可能になり、Linux、OS X、およびWindowsで同じように実行されます。
小さなWebブラウザ
ソケットライブラリを使用して、任意のインターネットプロトコルを実装できます。ここでは、たとえば、Webページのコンテンツをフェッチするコードがあります-
require 'socket'
host = 'www.tutorialspoint.com' # The web server
port = 80 # Default HTTP port
path = "/index.htm" # The file we want
# This is the HTTP request we send to fetch a file
request = "GET #{path} HTTP/1.0\r\n\r\n"
socket = TCPSocket.open(host,port) # Connect to server
socket.print(request) # Send request
response = socket.read # Read complete response
# Split response at first blank line into headers and body
headers,body = response.split("\r\n\r\n", 2)
print body # And display it
同様のWebクライアントを実装するには、次のようなビルド済みのライブラリを使用できます。 Net::HTTPHTTPを使用するため。これが前のコードと同等のコードです-
require 'net/http' # The library we need
host = 'www.tutorialspoint.com' # The web server
path = '/index.htm' # The file we want
http = Net::HTTP.new(host) # Create a connection
headers, body = http.get(path) # Request the file
if headers.code == "200" # Check the status code
print body
else
puts "#{headers.code} #{headers.message}"
end
FTP、SMTP、POP、およびIMAPプロトコルで動作するには、同様のライブラリを確認してください。
さらなる読み物
ソケットプログラミングのクイックスタートを提供しました。これは大きなテーマなので、Rubyソケットライブラリとクラスメソッドを調べて詳細を確認することをお勧めします。