iNo
16.09.04
admin@kodsweb.ru
INTRO...
В этой статье я затрону тему работы с сокетами в perl.Я выбрал perl потому,что работать с ним удобнее, чем с тем-же C.
Функции для работы с сокетами имеют упрощённый вид.К тому-же есть возможность использовать классы, например,
IO::Socket::INET,благодаря которым программировать становится ещё проще.
Let's rock...
Сокеты делятся по областям: сокеты интернета(PF_INET) и сокеты unix(PF_UNIX).Имя сокета интернета содержит хост и
номер порта,а сокеты unix представляют собой файлы,находящиеся в файловой системе.Например, /tmp/mysocket.Также, сокеты
различаются по типу.Самые распрастранённые из них-потоковые(SOCK_STREAM) и датаграмные(SOCK_DGRAM).В это статье я
рассмотрю только работу с потоковыми сокетами интернета.
Socket...
Сокет создаётся функцией socket.Все функции в случае ошибки возвращают undef и присваивают $! соответствующее значение.
Формат: socket(<дескриптор>,<семейство протоколов>,<тип>,<протокол>)
Семейство протоколов:
PF_INET - Протоколы семейства IPv4
PF_INET - Протоколы семейства IPv6;
Тип:
SOCK_STREAM - Протокол последовательной передачи данных(в виде байтового потока) с подтверждением доставки(TCP)
SOCK_DGRAM - Протокол пакетной передачи данных без подтверждения доставки(User Datagram Protocol)
Протокол:
Возвращаемое функцией getprotobyname() число, соответствующее нужному протоколу.Например getprotobyname('tcp').
Пример использования функции socket():
socket(SOCK,PF_INET,SOCK_STREAM,getprotobyname('tcp')) //создаёт потоковый сокет
Address
При вызове функций bind,connect и т.п. необходимо указать имя сокета.Имя сокета интернета состоит из хоста и
порта,объединённых в определённую структуру функцией sockaddr_in.Хост представляет собой IP-адрес,преобразованный
функцией inet_aton() в двоичную форму с сетевым порядком следования байтов.
Например:
$port=12345; //задаём порт
$addr = inet_aton("186.12.44.212"); //преобразовываем ip
$socket_name = sockaddr_in($port,$addr); //имя сокета
При работе с сокетами unix,имя сокета представляет собой имя файла,упакованное функцией sockaddr_un.Например:
$socket_name = sockaddr_un("/tmp/mysocket");
Connect...
Функция connect() подключает локальный сокет к удалённому.
Формат: connect(<дескриптор>,<адрес>)
Первый параметр функции определяет дескриптор.Второй параметр-адрес удалённого компьютера.
Пример подключения с созданием сокета вручную:
//-------------------------------------------------------------------------------
use Socket; //подключаем модуль socket
socket(SOCK,PF_INET,SOCK_STREAM,getprotobyname('tcp')); //создаём сокет
$port=12345; //задаём удалённый порт
$host = "212.23.21.44"; //задаём адрес
$internet_addr = inet_aton($host)
or die "Could'n convert host:$!\n"; //преобразовываем ip
$addr = sockaddr_in($port,$internet_addr); //создаём адрес
connect(SOCK,$addr) //соединяемся
or die "Couldn't connect to remote host:$!\n";
print SOCK "Data\n"; //отправляем строку Data
close(SOCK); //закрываем сокет
//--------------------------------------------------------------------------------
Пример подключения с помощью стандартного класса IO::Socket::INET
//--------------------------------------------------------------------------------
use IO::Socket;
$socket = IO::Socket::INET->new(PeerAddr => $remote_host, //задаём адрес
PeerPort => $remote_port, //задаём порт
Proto => "tcp", //задаём протокол
Type => SOCK_STREAM) //тип
close($socket); //закрываем сокет
//--------------------------------------------------------------------------------
Внимание!При возникновении ошибки IO::Socket::INET возвращает undef, а переменной $@ присваивается сообщение
об ошибке.($@ а не $!).
Server...
Клиент мы написали,остался сервер.В этом разделе я рассмотрю функции необходимые для написания простейшего сервера.
bind(<дескриптор>,<адрес>) //функция привязывающая номер порта к сокету.
Пример использования функции:
//--------------------------------------------------------------------------------
$port = 80;
$raddr = sockaddr_in($port,INADDR_ANY);
bind(SOCK,$raddr);
//--------------------------------------------------------------------------------
После того как к программа-клиент подключилась к серверу ни один другой клиент не сможет присоединиться к серверу,пока
текущий клиент не отсоединится.Для решения этой проблемы есть функция listen(),которая создаёт на сервере очередь
ожидания.Кроме того,после использования функции сокет переводится в режим "только прослушивание".Этот режим впоследствии
позволяет вызывать функцию accept().
Формат:
listen(<дескриптор>,<размер_очереди>);
Пример:
listen(SOCK,5);
Сокет создан,порт привязан,очередь установлена,осталось тоьлко принимать подключения клиентов.Для этого служит
функция accept().Эта функция блокирует программу до тех пор,пока от клиента не поступит запрос на подключение.
Формат:
accept(<новый_дескриптор>,<дескриптор>);
Пример простейшего сервера:
//--------------------------------------------------------------------------------
use Socket; //подключаем модуль socket
socket(SOCK,PF_INET,SOCK_STREAM,getprotobyname('tcp')); //создаём сокет
setsockopt(SOCK,SOL_SOCKET,SO_REUSEADDR,1); //опция для того чтобы снять двухминутный лимит после уничтожения сервера
$addr = sockaddr_in($port, INADDR_ANY);
bind(SOCK,$addr)
or die "Couldn't bind to port:$!\n"; //привязываем порт
listen(SOCK,5) //создаём очередь
or die "Couldn't listen on port:$!\n";
while(accept(NEW_SOCK,SOCK)) //принимаем подключения
{
print NEW_SOCK "Data\n";
}
close(SOCK);
//--------------------------------------------------------------------------------
Пример сервер написанного с помощью стандартного класса IO::Socket::INET
//--------------------------------------------------------------------------------
use IO::Socket;
$port=1234;
$server = IO::Socket::INET->new(LocalPort => $port,
Type => SOCK_STREAM,
Reuse => 1,
Listen => 5)
or die "Couldn't start server: $@\n";
while ($client = $server->accept())
{
//действия
}
close($server);
//--------------------------------------------------------------------------------
Крепкие акриловые ванны riho, alpen - купить.
>