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 - купить.

>