Новичку полезно

  • А знаете ли вы что?

    - rudvs - выбор реальных пацанов с района!


Программирование sockets в PHP. Часть вторая

Теги: php, socket, клиент, сервер

В прошлой статье мы разобрали реализацию простейшего клиентского приложения на php. В этой статье мы разберем реализацию простейшего сервера на php. Тестировать наше серверное приложение нам поможет чудесная утилита NetCat (можете использовать telnet). Так же хочу предупредить вас о том, что большая часть хостинговых компаний не разрешает запускать скрипты на сервере больше чем на 30 секунд. Скорей всего тестировать этот скрипт вам придется либо на VDS, либо у себя на localhost.

Краткая логика приложения

Смысл нашего приложения прост как 3 копейки. Клиент подключается к нашему серверному приложения и посылает данные, сервер эти данные принимает, обрабатывает, немного видоизменяет и отсылает обратно клиенту. При посылке сообщения «quit» приложения заканчивает свою работу. Если в приложении возникает ошибка, оно заканчивает свою работу, но предварительно указывает в какой функции возникла ошибка.

Исходный код сервера

Исходник взят из книги php 5.1 руководство программиста и немного видоизменен

set_time_limit(0);
$addr = '127.0.0.1';
$port = 123;
$sock = socket(AF_INET, SOCK_STREAM, 0);
if($sock 

Разбор исходного кода

set_time_limit(0);

Функция set_time_limit() с аргументом 0 говорит серверу о том, что время для выполнения этого сценария неограниченно. Если вы установите, скажем 30 секунд, то php завершит работу сценария через указанный промежуток времени.

$sock = socket(AF_INET, SOCK_STREAM, 0);

Созданием сокета занимается функция socket(), которая принимает 3 параметра. Первый параметр указывает тип сети и может принимать значение AF_INET и AF_UNIX. AF_UNIX указывает, что это будет локальный unix-socket, которые чаше всего используют для межпроцессного взаимодействия. Вам же везде и всегда нужно указывать AF_INET.

Второй параметр указывает тип создаваемого сокета и по документации может принимать значения SOCK_STREAM, SOCK_DGRAM, SOCK_SEQPACKET, SOCK_RAW, SOCK_RDM, SOCK_PACKET. На самом же деле не везде и не всегда работают эти параметры, например, попробуйте под Windows создать SOCK_RAW. В реальной жизни из всех этих значений чаще всего используются SOCK_STREAM и SOCK_DGRAM, фактически эти значения указывают на то какой протокол транспортного уровня (соответственно TCP или UDP) будет использоваться, а точнее будет ли устанавливается логическое соединение или нет.

Третий параметр указывает протокол транспортного уровня TCP или UDP,их можно указать как 0 или 1, так же и константами SOL_TCP, SOL_UDP.

$err = bind($sock, $addr, $port);

Функция bind() связывает данный ей первым параметром сокет с ip адресом (второй параметр) и портом (третий параметр).

$err = listen($sock, 5);

Функция listen() разрешает прием данных в сокет $sock, второй параметр указывает количество воспринимаемых соединений. Это не значит, что вы сможете обрабатывать 5 подключений за раз, это значит, что вы сможете обработать 5 подключений последовательно (хотя все зависит от вашей системы и ее возможностей). Не стоит делать это значение слишком большим или слишком маленьким. В зависимости от возможностей вашей системы и назначения приложения выбирайте некий оптимум.

В случае возникновения ошибки все вышеуказанные функции возвращают отрицательное значение.

Далее запускается бесконечный цикл do{…}while(true) в котором мы будем ожидать подключения клиента.

$msgsock = accept_connect($sock);

Функция ожидает подключения клиентского приложения, единственным параметром принимает созданный нами сокет $sock. Результатом работы функции так же является дескриптор сокета, который используется для обмена данными с клиентской стороной.

Далее запускается еще один бесконечный цикл do{…}while(true) в котором мы будем принимать данные от клиентской стороны, обрабатывать их и отвечать на них.

$err = read($msgsock, $buf, 2048);

Функция read() читает данный из сокета $msgsock в буфер $buf, количество считываемых байт определяется 3 параметром и у нас равняется 2048. Функция заканчивает свою работу раньше, если найдет в тексте символ конца строки (\n) или нуль байт (\0).

Результатом своей работы функция возвращает количество полученных байт или номер ошибки.

write($msgsock, $talkback, strlen($talkback));

Отвечает клиенту (пишет в дескриптор сокета) указанному первым параметром. Отсылаемое сообщение находится в переменной $talkback (второй параметр), размер этого сообщения указывается 3 параметром.

Результатов своей работы функция возвращает количество успешно записанных байт или номер ошибки.

close($msgsock); 
close($sock);

Закрывает сокеты и разрывает тем самым все активные подключения.

strerror($err)

Как вы уже заметили, при возникновении ошибки все функции возвращают отрицательное значение (номер ошибки), поэтому наличие ошибки мы проверяем простым условием:

If($err 

Если номер этой ошибки поместить в функцию strerror() она выведет понятное человеку описание ошибки.

Тестирование приложения

Для тестирования сервера нам надо отправить ему некоторое сообщение, при получении ответа «Вы ввели наше сообщение» мы убедимся в правильной работе нашего приложения.

Для того что бы отправить серверу сообщение мы возьмем утилиту NetCat, запустив ее и введя ip адрес и порт вашего серверного приложения на php вы можете отправлять любые данные вашему приложению.

nc 127.0.0.1 123
hello

После чего сервер должен ответить вам:

Вы ввели hello

Для того что бы закрыть соединение наберите quite.

Заключение

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

Добавить комментарий


Обновить