English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Programación de sockets en Ruby

Ruby ofrece dos niveles de acceso a servicios de red, en la capa inferior puedes acceder al sistema operativo, lo que te permite implementar soporte básico de sockets orientados a conexión y sin conexión para clientes y servidores.

Ruby admite unificadamente los protocolos de red de aplicación, como FTP, HTTP, etc.

Ya sea a nivel superior o inferior. Ruby proporciona algunas clases básicas que le permiten interactuar con muchos protocolos como TCP, UDP, SOCKS, sin estar limitado a la capa de red. Estas clases también proporcionan clases auxiliares que le permiten leer y escribir fácilmente en servidores.

Ahora, vamos a aprender cómo realizar programación de Socket en Ruby

¿Qué son Sockets?

Cuando la capa de aplicación se comunica a través de la capa de transporte, TCP y UDP se enfrentan al problema de proporcionar servicios concurrentes a múltiples procesos de aplicación. Múltiples conexiones TCP o múltiples procesos de aplicación pueden necesitar transmitir datos a través del mismo puerto del protocolo TCP. Para distinguir diferentes procesos de aplicación y conexiones, muchos sistemas operativos de computadoras proporcionan una interfaz llamada Socket para la interacción entre aplicaciones y el protocolo TCP/IP, para distinguir la comunicación de red y conexión entre diferentes procesos de aplicación.

La generación de sockets, principalmente3Los parámetros: la dirección IP de destino de la comunicación, el protocolo de capa de transporte utilizado (TCP o UDP) y el número de puerto utilizado. El significado original de Socket es "enchufe". A través de esto3Los parámetros combinados, al asociarse con un "enchufe" Socket, permiten que la capa de aplicación se comunique a través de la interfaz de socket con la capa de transporte, distinguiendo la comunicación de diferentes procesos de aplicación o conexiones de red, para implementar servicios de transmisión concurrente de datos.

Análisis de vocabulario de Sockets:

OpcionesDescripción
domainIndica la familia de protocolos utilizados, generalmente PF_INET, PF_UNIX, PF_X25, etc.
typeEspecifica el tipo de socket: SOCK_STREAM o SOCK_DGRAM, la interfaz de Socket también define Socket de nivel original (SOCK_RAW), lo que permite que el programa utilice protocolos de bajo nivel
protocolPor lo general se asigna 0.
hostnameIdentificador de interfaz de red:
  • Cadena, puede ser el nombre del host o la dirección IP

  • La cadena "<broadcast>", especifica la dirección INADDR_BROADCAST.

  • Cadena de longitud 0, especifica INADDR_ANY

  • Un entero, que se interpreta como la dirección binaria de orden de bytes del host.

puertoEl número de puerto es el identificador del puerto, cada servidor escucha una o más puertos de conexión de clientes, un número de puerto puede ser un número entero, que contiene el nombre del servidor y el puerto.

Cliente simple

A continuación, hemos escrito un ejemplo de cliente simple proporcionando un host y un puerto, la clase Ruby TCPSocket ofrece el método open para abrir un socket.

TCPSocket.open(hosname, port) abre una conexión TCP.

Una vez que abre una conexión de Socket, puede leerla como un objeto IO y, una vez completada, debe cerrar la conexión de la misma manera que cerraría un archivo.

El siguiente ejemplo muestra cómo conectarse a un host específico, leer datos desde el socket y, finalmente, cerrar el socket:

Ejemplo en línea

require 'socket' # Sockets son una biblioteca estándar
 
hostname = 'localhost'
port = 2000
 
s = TCPSocket.open(hostname, port)
 
while line = s.gets # Leer cada línea de datos del socket
  puts line.chop # Imprimir en la terminal
end
s.close # Cerrar el socket

Servicio simple

Ruby permite escribir servicios sencillos utilizando la clase TCPServer. El objeto TCPServer es una fábrica de objetos TCPSocket.

Ahora utilizamos TCPServer.open(hostname, port) para crear un objeto TCPServer.

A continuación, se llama al método accept de TCPServer, que espera a que un cliente se conecte al puerto especificado y luego devuelve un objeto TCPSocket que representa la conexión con el cliente.

Ejemplo en línea

require 'socket' # Obtener la biblioteca estándar de socket
 
server = TCPServer.open(2000) # El puerto de escucha del Socket es 2000
loop { # Ejecutar el servicio de manera perpetua
  client = server.accept # Esperar por la conexión del cliente
  client.puts(Time.now.ctime) # Enviar la hora al cliente
  client.puts "Cerrando la conexión. ¡Adiós!"
  client.close # Cerrar la conexión del cliente
}

Ahora, ejecute el código en el servidor y observe los resultados.

Servicio TCP multiconexion

En Internet, la mayoría de los servicios tienen una gran cantidad de conexiones de clientes.

Ruby permite crear servicios multihilo de manera sencilla con la clase Thread, donde un hilo maneja la conexión del cliente y el hilo principal espera por más conexiones.

Ejemplo en línea

require 'socket' # Obtener la biblioteca estándar de socket
 
server = TCPServer.open(2000) # Puerto de escucha del socket 2000
loop { # Servidor ejecutándose permanentemente
  Thread.start(server.accept) do |client|
    client.puts(Time.now.ctime) # Enviar tiempo al cliente
    client.puts "Cerrando la conexión. ¡Adiós!"
    client.close # Cerrar conexión del cliente
  end
}

En este ejemplo, el socket se ejecuta permanentemente, y cuando server.accept recibe la conexión del cliente, se crea un nuevo hilo que comienza a procesar la solicitud inmediatamente. Mientras tanto, el programa principal vuelve al bucle y espera una nueva conexión.

Mini navegador web

Podemos usar la biblioteca socket para implementar cualquier protocolo de Internet. A continuación se muestra cómo obtener el contenido de una página web:

Ejemplo en línea

require 'socket'
 
host = 'es.oldtoolbag.com' # Servidor web
port = 80 # Puerto HTTP predeterminado
path = "/index.htm" # Dirección del archivo que deseas obtener
 
# Esta es una solicitud HTTP
request = "GET #{path} HTTP/1.0\r\n\r\n"
 
socket = TCPSocket.open(host,port) # Conectar al servidor
socket.print(request) # Enviar solicitud
response = socket.read # Leer la respuesta completa
# Dividir la respuesta en encabezados y cuerpo en la primera línea en blanco
headers,body = response.split("\r\n\r\n", 2) 
print body # Imprimir resultado

Para implementar un cliente similar a web, puedes usar bibliotecas preconstruidas para HTTP como Net::HTTP.

El siguiente código es equivalente al anterior:

Ejemplo en línea

require 'net/http' # Bibliotecas necesarias
host = 'es.oldtoolbag.com'           # Servidor web
path = '/index.htm'                 # El archivo que queremos 
 
http = Net::HTTP.new(host)          # Crear conexión
headers, body = http.get(path)      # Solicitar archivo
if headers.code == "200"            # Verificar el código de estado
  print body                        
else                                
  puts "#{headers.code} #{headers.message}" 
end

Aquí solo hemos presentado de manera sencilla la aplicación de sockets en Ruby, para más documentación, consulte:Biblioteca de sockets de Ruby y métodos de clase