Ruby - Programação de Soquete

Ruby fornece dois níveis de acesso a serviços de rede. Em um nível inferior, você pode acessar o suporte de soquete básico no sistema operacional subjacente, que permite implementar clientes e servidores para protocolos orientados a conexão e sem conexão.

Ruby também tem bibliotecas que fornecem acesso de nível superior a protocolos de rede de nível de aplicativo específicos, como FTP, HTTP e assim por diante.

Este capítulo fornece uma compreensão do conceito mais famoso em Rede - Programação de Soquete.

O que são soquetes?

Os soquetes são os terminais de um canal de comunicação bidirecional. Os soquetes podem se comunicar dentro de um processo, entre processos na mesma máquina ou entre processos em continentes diferentes.

Os soquetes podem ser implementados em vários tipos de canais diferentes: soquetes de domínio Unix, TCP, UDP e assim por diante. O soquete fornece classes específicas para lidar com os transportes comuns, bem como uma interface genérica para lidar com o resto.

Os soquetes têm seu próprio vocabulário -

Sr. Não. Termo e descrição
1

domain

A família de protocolos que será usada como mecanismo de transporte. Esses valores são constantes como PF_INET, PF_UNIX, PF_X25 e assim por diante.

2

type

O tipo de comunicação entre os dois pontos de extremidade, normalmente SOCK_STREAM para protocolos orientados à conexão e SOCK_DGRAM para protocolos sem conexão.

3

protocol

Normalmente zero, isso pode ser usado para identificar uma variante de um protocolo dentro de um domínio e tipo.

4

hostname

O identificador de uma interface de rede -

Uma string, que pode ser um nome de host, um endereço quádruplo com pontos ou um endereço IPV6 em notação de dois pontos (e possivelmente ponto)

Uma string "<broadcast>", que especifica um endereço INADDR_BROADCAST.

Uma string de comprimento zero, que especifica INADDR_ANY, ou

Um número inteiro, interpretado como um endereço binário na ordem de bytes do host.

5

port

Cada servidor escuta os clientes chamando em uma ou mais portas. Uma porta pode ser um número de porta Fixnum, uma string contendo um número de porta ou o nome de um serviço.

Um cliente simples

Aqui, escreveremos um programa cliente muito simples, que abrirá uma conexão para uma determinada porta e um determinado host. Aula de RubyTCPSocketfornece a função aberta para abrir tal soquete.

o TCPSocket.open(hosname, port )abre uma conexão TCP para o nome do host na porta .

Depois de ter um soquete aberto, você pode ler dele como qualquer objeto IO. Quando terminar, lembre-se de fechá-lo, como você fecharia um arquivo.

O código a seguir é um cliente muito simples que se conecta a um determinado host e porta, lê todos os dados disponíveis do soquete e sai -

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

Um servidor simples

Para escrever servidores de Internet, usamos o TCPServerclasse. Um objeto TCPServer é uma fábrica de objetos TCPSocket.

Agora ligue TCPServer.open(hostname, portfunção para especificar uma porta para o seu serviço e criar umTCPServer objeto.

Em seguida, chamar a aceitar método do objeto TCPServer retornado. Este método espera até que um cliente se conecte à porta especificada e, em seguida, retorna um objeto TCPSocket que representa a conexão com esse cliente.

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
}

Agora, execute este servidor em segundo plano e execute o cliente acima para ver o resultado.

Servidores TCP de múltiplos clientes

A maioria dos servidores na Internet é projetada para lidar com um grande número de clientes a qualquer momento.

A classe Thread do Ruby facilita a criação de um servidor multithread. Um que aceita solicitações e cria imediatamente um novo thread de execução para processar a conexão enquanto permite que o programa principal aguarde mais conexões -

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
}

Neste exemplo, você tem um loop permanente e, quando server.accept responde, um novo thread é criado e iniciado imediatamente para lidar com a conexão que acabou de ser aceita, usando o objeto de conexão passado para o thread. No entanto, o programa principal retorna imediatamente e aguarda novas conexões.

Usar threads Ruby dessa forma significa que o código é portátil e será executado da mesma maneira no Linux, OS X e Windows.

Um Tiny Web Browser

Podemos usar a biblioteca de soquetes para implementar qualquer protocolo da Internet. Aqui, por exemplo, está um código para buscar o conteúdo de uma página da 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

Para implementar o cliente da web semelhante, você pode usar uma biblioteca pré-construída como Net::HTTPpara trabalhar com HTTP. Aqui está o código que faz o equivalente ao código anterior -

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

Verifique se bibliotecas semelhantes funcionam com protocolos FTP, SMTP, POP e IMAP.

Leituras adicionais

Fornecemos um guia rápido para programação de soquetes. É um assunto extenso, portanto, é recomendável que você consulte a Biblioteca de Soquetes Ruby e Métodos de Classe para encontrar mais detalhes.