Введение в CGI

Работа с серверами Internet. Сокеты


Пусть и не очень часто, но все-таки приходится при разработке CGI-скриптов пользоваться возможностью обращения из скрипта к серверу, установленному на другом компьютере. При работе в сетях TCP/IP для этой цели используют библиотеку сокетов (Berkeley sockets) TCP/IP. Сокет — это пара "IP-адрес — номер порта". При программировании речь, конечно, будет идти о структуре данных, которая позволяет передать/принять данные с удаленного компьютера.

IP-адрес в сокете отвечает за доступ к определенному компьютеру в Internet. В общем случае IP-адреса закрепляются не за отдельными компьютерами, а за сетевыми интерфейсами. Один сетевой интерфейс может иметь несколько IP-адресов. Эта возможность используется при организации виртуальных Web-узлов.

Порт — это виртуальный канал приема/передачи данных, в котором происходит обслуживание приходящих из сети запросов. Этот канал обозначается цифрой. Первые 256 каналов — это WKS (Well Known Services, "хорошо известные" сервисы). Например, за HTTP-обменом закреплен 80-й порт, за FTP-обменом – 20-й и 21-й порты, за DNS (Domain Name System, служба доменных имен) – 53-й порт и т.д.

Порты бывают двух типов, TCP и UDP (User Data Protocol, пользовательский протокол данных), т.е. соответствуют типу транспортного протокола, который используется для передачи данных. Мы будем рассматривать в качестве примера именно TCP, т.к. HTTP-обмен использует только TCP-порты. Слово "порты" во множественном числе здесь употребляется не случайно. Дело в том, что только первоначальное обращение к HTTP-серверу происходит по 80-му порту. Для того чтобы обслуживать много запросов практически одновременно, сервер переназначает порт, и клиент, например, браузер, общается с сервером уже по другому порту.

Кроме TCP/IP существуют еще и другие виды сокетов, поэтому при программировании нужно указывать тип сокета. Ниже приведен пример обращения из скрипта к серверу HTTP:

#!/usr/local/bin/perl use IO::Socket; $remote = IO::Socket::INET->new( Proto=>"tcp", PeerAddr=>"localhost", PeerPort=>"80" ) or die "No service"; $remote->autoflush(1); print $remote "HEAD / HTTP/1.0\n\n"; while() { print; } -close $remote;

В данном примере используется пакет Socket из библиотеки IO (Interpretive Operation, работа в режиме интерпретации) (оператор use). В третьей строчке примера происходит открытие дескриптора для сокета. Затем этот дескриптор применяется как обычный дескриптор файла, который открыт для записи и чтения.

Прежде чем писать данные в сокет, обычно отменяют буферизацию (autoflush(1) — выталкиваем по одному байту). Делается это для того, чтобы данные сразу уходили на сервер. В противном случае сервер может разорвать соединение, не дождавшись запроса.

Оператор print демонстрирует запрос по протоколу HTTP 1.0 к HTTP-серверу. В этом запросе просто считывается документ из корня каталога HTTP-сервера. Обычно это файл index.html. Чтение отклика происходит в цикле while. После считывания отклика socket закрывается по функции -close.



Содержание раздела