Учебники

Ruby — Socket Программирование

Ruby обеспечивает два уровня доступа к сетевым сервисам. На низком уровне вы можете получить доступ к базовой поддержке сокетов в базовой операционной системе, которая позволяет реализовывать клиенты и серверы как для протоколов, ориентированных на соединение, так и для протоколов без установления соединения.

В Ruby также есть библиотеки, которые предоставляют высокоуровневый доступ к определенным сетевым протоколам прикладного уровня, таким как FTP, HTTP и так далее.

Эта глава дает вам понимание самой известной концепции в сети — Socket Programming.

Что такое сокеты?

Сокеты являются конечными точками двунаправленного канала связи. Сокеты могут связываться внутри процесса, между процессами на одной машине или между процессами на разных континентах.

Сокеты могут быть реализованы для нескольких различных типов каналов: доменные сокеты Unix, TCP, UDP и т. Д. Сокет предоставляет специальные классы для обработки общих транспортов, а также универсальный интерфейс для обработки остальных.

Сокеты имеют свой собственный словарь —

Sr.No. Срок и описание
1

домен

Семейство протоколов, которые будут использоваться в качестве транспортного механизма. Эти значения являются константами, такими как PF_INET, PF_UNIX, PF_X25 и так далее.

2

тип

Тип связи между двумя конечными точками, обычно SOCK_STREAM для протоколов, ориентированных на соединение, и SOCK_DGRAM для протоколов без установления соединения.

3

протокол

Обычно ноль, это может использоваться для идентификации варианта протокола в домене и типе.

4

имя хоста

Идентификатор сетевого интерфейса —

Строка, которая может быть именем хоста, четырехточечным адресом или IPV6-адресом в двоеточии (и, возможно, точечной) нотации.

Строка «<broadcast>», которая указывает адрес INADDR_BROADCAST.

Строка нулевой длины, которая указывает INADDR_ANY, или

Целое число, интерпретируемое как двоичный адрес в порядке байтов хоста.

5

порт

Каждый сервер прослушивает клиентов, звонящих на один или несколько портов. Порт может быть номером порта Fixnum, строкой с номером порта или названием службы.

домен

Семейство протоколов, которые будут использоваться в качестве транспортного механизма. Эти значения являются константами, такими как PF_INET, PF_UNIX, PF_X25 и так далее.

тип

Тип связи между двумя конечными точками, обычно SOCK_STREAM для протоколов, ориентированных на соединение, и SOCK_DGRAM для протоколов без установления соединения.

протокол

Обычно ноль, это может использоваться для идентификации варианта протокола в домене и типе.

имя хоста

Идентификатор сетевого интерфейса —

Строка, которая может быть именем хоста, четырехточечным адресом или IPV6-адресом в двоеточии (и, возможно, точечной) нотации.

Строка «<broadcast>», которая указывает адрес INADDR_BROADCAST.

Строка нулевой длины, которая указывает INADDR_ANY, или

Целое число, интерпретируемое как двоичный адрес в порядке байтов хоста.

порт

Каждый сервер прослушивает клиентов, звонящих на один или несколько портов. Порт может быть номером порта Fixnum, строкой с номером порта или названием службы.

Простой клиент

Здесь мы напишем очень простую клиентскую программу, которая откроет соединение с данным портом и данным хостом. Класс Ruby TCPSocket предоставляет функцию open для открытия такого сокета.

TCPSocket.open (имя хоста, порт) открывает TCP-соединение с именем хоста на порту .

Когда у вас есть открытый сокет, вы можете читать из него, как любой объект ввода-вывода. Когда закончите, не забудьте закрыть его, как вы бы закрыли файл.

Следующий код представляет собой очень простой клиент, который подключается к данному хосту и порту, читает все доступные данные из сокета и затем завершает работу.

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 (имя хоста, функция порта, чтобы указать порт для вашей службы и создать объект TCPServer .

Затем вызовите метод accept возвращенного объекта TCPServer. Этот метод ожидает подключения клиента к указанному вами порту и возвращает объект 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-серверы

Большинство серверов в Интернете предназначены для одновременной работы с большим количеством клиентов.

Класс Thread в Ruby позволяет легко создавать многопоточный сервер. Он принимает запросы и сразу же создает новый поток выполнения для обработки соединения, позволяя основной программе ожидать больше соединений.

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.

Крошечный веб-браузер

Мы можем использовать библиотеку сокетов для реализации любого интернет-протокола. Вот, например, код для извлечения содержимого веб-страницы —

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

Для реализации аналогичного веб-клиента вы можете использовать готовую библиотеку, такую ​​как Net :: HTTP, для работы с HTTP. Вот код, который делает эквивалент предыдущего кода —

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 Socket и методы классов, чтобы узнать больше.