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