CFA LogoCFA Logo Computer
Новости Статьи Магазин Драйвера Контакты
Новости
RSS канал новостей
В конце марта компания ASRock анонсировала фирменную линейку графических ускорителей Phantom Gaming. ...
Компания Huawei продолжает заниматься расширением фирменной линейки смартфонов Y Series. Очередное ...
Компания Antec в своем очередном пресс-релизе анонсировала поставки фирменной серии блоков питания ...
Компания Thermalright отчиталась о готовности нового высокопроизводительного процессорного кулера ...
Компания Biostar сообщает в официальном пресс-релизе о готовности флагманской материнской платы ...
Самое интересное
Программаторы 25 SPI FLASH Адаптеры Optibay HDD Caddy Драйвера nVidia GeForce Драйвера AMD Radeon HD Игры на DVD Сравнение видеокарт Сравнение процессоров

АРХИВ СТАТЕЙ ЖУРНАЛА «МОЙ КОМПЬЮТЕР» ЗА 2003 ГОД

Сквозь Socket к Инету

Дмитрий СВИРЕПЧУК dima_sdi@i.com.ua

Сегодня речь вновь пойдет о замечательном языке серверных приложений — о PHP. Я покажу, как на нем можно написать, ни много ни мало, программу чтения USENET-новостей.

Что такое USENET? Это бесконечное пространство для общения (подробнее см. статью Валерия Аксака «Интернет-андеграунд + ФИДО = Usenet» в МК 39(158)). Чтобы подробно узнать, «как туда попасть», можно открыть справку Outlook Express и зайти в раздел «Работа с группами новостей». Я же дам краткую характеристику. В USENET есть огромнейшее количество групп новостей (как их называют, эхо-конференций, форумов). Стоит заметить, что «новости» — это лишь формальное название, которое не имеет отношения к УНІАН. Все группы строго разделены по тематике. Пользователи, подписываясь на определенный форум, получают возможность читать письма других участников и самостоятельно отправлять письма в группу. Поскольку новости читает большое количество людей, вы можете быстро получить ответ на возникший вопрос и так же быстро испытать моральное удовлетворение, помогая найти ответы другим.

Работает все это чудо по протоколу NNTP (Network News Transfer Protocol — Протокол Передачи Сетевых Новостей). Полное описание данного протокола можно найти по адресу http://www.w3.org/Protocols/rfc977/rfc977.html.

Сейчас мы «наскриптим» скрипт, который будет представлять из себя программу для чтения конференций (ньюсридер, как ее называют «кулхацкеры»).

Перед тем как приступить к практике — немного теории. Весь процесс работы с NNTP-сервером заключается в том, чтобы:

1. Открыть соединение, или, как говорят, TCP Socket (socket — розетка);

2. При необходимости идентифицироваться на сервере — передать логин и пароль;

3. Получить информацию о конкретной группе или нескольких группах. Что именно? Список групп, доступных на сервере, количество новых статей (или их общее количество) в выбранной группе.

4. При необходимости можно загрузить все сообщения или только их заголовки (поля «От:», «Тема:» и т.д.). Можно запостить письмо.

5. В конце всех действий нужно закрыть соединение (сокет).

Вот, в принципе, и все действия, к которым сводится процесс общения с сервером. Но проще сказать, чем сделать.

Теперь надо решить, чего мы ожидаем от нашего скрипта.

Поскольку скрипт, который я буду здесь описывать — простенький (но функционирующий) пример, он будет всего лишь уметь писать и отправлять письма в конференцию. Приступим к созданию html-страницы, из которой будет вызываться наш скрипт.

Форма вполне стандартна, но тем не менее я опишу ее поля:

ServerName — сюда пользователь будет вводить имя (или IP-адрес) сервера USENET;

UserLogin, UserPass — логин и пароль пользователя на сервере, соответственно.

GroupName — определяет имя группы новостей, из которой будут браться сообщения для отображения и куда будет отправлено сообщение, написанное пользователем;

MessLimit — ниспадающий список из трех пунктов (5/10/15). В нем выбирается количество сообщений, которые должны быть отображены в браузере.

Следующий блок полей определяет заголовки исходящего письма, а также его текст.

В конце две стандартные кнопки Reset и Submit. При нажатии на последнюю данные из формы пересылаются в скрипт, который находится в файле nntpclient.php.

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

Теперь я приведу скрипт с вкрапленными в него комментариями.

Функция fsockopen() работает практически аналогично функции fopen(), которая предназначена для открытия файлов. Разница в том, что fsockopen() применяется для установления соединения с удаленным компьютером. В качестве первого параметра указывается либо имя сервера, либо его IP-адрес. Второй параметр — это порт, к которому нужно подключится. Все NNTP-серверы работают на 119-м порту, который мы и указали в качестве параметра. Полный вид функции вот такой: int fsockopen (string hostname,int port [, int errno [, string errstr [, float timeout]]]). Следующие три необязательных параметра задают, соответственно: номер ошибки (в случае появления), ее строковое значение, и таймер. Таймер определяет время, через которое нужно дать отбой, если сервер не откликается.

Если соединение было выполнено успешно, тогда функция возвращает дескриптор соединения, если же вызов провалился, тогда 0 (ноль). Результат заносится в переменную $nntpsock. Как известно, в PHP понятия 0 и false практически эквивалентны, следовательно, если установить соединение с сервером не удалось, условие в операторе if принимает значение true. Вследствие этого выводится сообщение об ошибке, и скрипт останавливается. Если же соединение прошло успешно, скрипт продолжает работу.

А теперь, о чудо, оказывается, что для обмена данными с сокетом применяются те же самые функции, что и для работы с файлами для построчного чтения и записи: fgets() и fputs(). При работе с сокетом нужно постоянно помнить одну важную деталь. Всегда после открытия сокета и передачи ему какой-либо информации необходимо считывать очередную строку (даже если она нам не нужна), тем самым перематывая «файл» в конец. Это необходимо потому, что вывод буферизируется, и при последующем обращении к сокету мы будем получать не ту строку, что надо, а более раннюю. В переменную $answer мы всегда будем считывать последний ответ сервера.

Здесь мы поочередно передаем серверу две команды: AUTHINFO USER логин_пользователя \n и AUTHINFO PASS пароль_пользователя\n. Они предназначаются для передачи серверу логина и пароля, введенных пользователем. Стоит обратить внимание на то, что в конце любой команды обязательно нужно ставить символ новой строки: \n.

Если логин и пароль были указаны верно, сервер скажет: 281 OK. Но поскольку эта фраза может быть сильно «приукрашена» ведущими и заключающими символами \r и \n, мы воспользуемся функцией trim(), чтобы отсечь их. Если же логин и пароль были указаны неверно, то выведется соответствующее сообщение, и скрипт остановится.

Теперь необходимо передать серверу информацию о том, с какой группой мы хотим работать — без этого нельзя. Делается это путем передачи команды GROUP имя_группы. После этого сервер вернет строку типа:

где:

211 — код, обозначающий, что команда распознана, группа выбрана, и все просто чудесно;

a — количество новых сообщений;

b — номер первой статьи (самой старой);

c — номер последней статьи (самой новой).

Итак, при помощи функции substr() мы проверили, начинается ли ответ сервера с цифр 211. Если нет, выводится соответствующее сообщение, и скрипт прекращает работу.

Теперь при помощи функции split() мы разделяем полученную строку, используя в качестве разделителя пробел. В результате получился массив $GroupInfo следующего содержания:

То, что идет дальше, нам не интересно. Для уведомления пользователя о состоянии выбранной им группы выводится сообщение с полученными данными:

В этом блоке выполняется проверка количества статей в выбранной группе. Если общее количество статей (номер_последней —номер_первой) в данной группе меньше, чем пользователь хочет посмотреть ($MessLimit), то тогда скрипт будет выводить только существующее количество статей.

Теперь выводим последних $MessLimit статей, которые есть в выбранной группе. Вывод производится с минимальным форматированием. Для того чтобы получить статью, нужно передать серверу команду ARTICLE номер_статьи. Если такая статья есть, тогда сервер ответит:

где:

220 — опять же код, указывающий на то, что команда распознана;

n — номер статьи на сервере;

<a> — message-ID: уникальный идентификатор статьи.

Стоит сказать пару слов о номере статьи и ее идентификаторе. Номер статьи может меняться со временем (при получении сервером новых сообщений, например). Идентификатор же не изменится никогда, но может случиться иное: сервер присвоит такой же идентификатор другому сообщению. Но это случается крайне редко — раз в несколько лет, а к этому времени первая статья, согласитесь, устареет.

После передачи сервером вышеуказанной строки он передает сам текст сообщения: сначала все имеющиеся заголовки, а потом текст статьи. При этом заголовки отделяются от текста одной пустой строкой. Признак конца сообщения выглядит так: \r\n.\r\n (обратите внимание на точку между \r\n). Здесь использован один из двух возможных форматов команды ARTICLE — по номеру статьи. Есть также второй вариант —ARTICLE <message-ID>. Такой формат применяется, если нужно получить статью по ее идентификатору.

Кроме ARTICLE есть еще команды HEADER и BODY для получения только заголовков статьи или же только самого текста. Эти две команды, как и ARTICLE, можно использовать как с номером статьи, так и с ее идентификатором.

На этом процесс получения писем заканчивается, и мы приступаем к отправке сообщения, введенного пользователем. Если пользователь ничего не набрал, значит и отправлять нечего — выходим из скрипта:

Декоративная горизонтальная линия, которая отделит отображенные статьи от последующего вывода:

А теперь посылаем серверу команду POST:

Если все в порядке, сервер вернет строку

где:

340 — код, означающий, что все в порядке. Далее сервер сообщает, что нам можно отправить статью, которую нужно закончить уже упоминавшейся последовательностью \r\n.\r\n.

Если постить в группу запрещено, тогда ответ будет выглядеть так: 440 posting not allowed — извините, не повезло.

Формируем готовое к отправке сообщение (со всеми заголовками и окончанием) в переменной $ConvertedMess. Добавляем заголовки, введенные пользователем из формы. Как я уже говорил, первая пустая строка в сообщении означает, что все написанное дальше — текст сообщения. Иногда можно попасться на этом, написав вот так:

И вновь напоминаю: не забудьте заканчивать сообщение последовательностью \r\n.\r\n. Если сервер ее не найдет, то сообщение будет забраковано и не принято.

Теперь передаем сообщение.

Выводим небольшое сообщение о том, что все «пучком».

Конец скрипта.

Ну вот, осталось только все это набрать, запустить и радоваться. Казалось бы, можно процитировать песню: «Ти просто молодчина, я просто молодець, на цьому все — казочці… кінець». Но тут донеслись крики: «Как это все? А практические рекомендации, советы, выезд на дом с установкой предлагаемого программного обеспечения!?»

Ладно, уговорили.

Первая проблема состоит в том, что некрасиво заваливать группы новостей всякими сообщениями типа «Test». Да и дорого это, тестировать скрипт в онлайне. Вывод напрашивается сам собой: нужно обзавестись NNTP-сервером. Не обязательно, чтобы он был суперкрутым, ведь мы хотим не администрировать новостной сервер, а всего лишь проверить скрипт. Мне в решении этой проблемы помог Eserv (http://www.eserv.ru/eserv/files/eserv299.exe, 1.60 Мб). Программа сочетает в себе функции WWW-, FTP-, POP3-, SMTP-, PROXY-, FINGER- и NNTP-серверов. Так сказать, «все в одном флаконе». Иногда софтина глючит, но в целом весьма функциональна.

Теперь посмотрим, чему мы научились. Во-первых, разобрали механизм использования сокетов в PHP на полезном примере. Таким образом, можно подсоединяться не только к 119 порту, но и к любому другому (за которым следит определенная программа). Частично разобрались с протоколом сетевых новостей. Я описал далеко не все команды протокола NNTP. Для того чтобы получить его полное описание, достаточно лишь зайти на страницу с описанием RFC977 (Request For Comment 977), URL которой указан выше. При желании можно написать крутой USENET-гейт.

Открою секрет: подобно NNTP-протоколу работают и POP, и SMTP (которые применяются для обмена почтой), и все остальные протоколы. Теперь перестает быть секретом, как работает web-интерфейс для почты. Даже HTTP, которым пользуются все (но не все знают об этом), тоже работает по аналогичному принципу.

Для того чтобы понять, как работают все эти протоколы, обратитесь к соответствующим описаниям RFC на сайте http://www.w3.org. Притом что наш скрипт работает на PHP, это вовсе не означает, что сей язык — единственный, поддерживающий сокеты. Их поддержка реализована, например, в том же Delphi, да и во многих других языках программирования, не применяющихся в web-программировании.

P.S. Проверить работу скрипта можно по адресу http://www.vodo-oblik.com.ua/nntp, а скачать его текст здесь: http://www.vodo-oblik.com.ua/nntp/nntp_client.zip(ЦЕЛЫХ два килобайта).

Рекомендуем ещё прочитать:






Данную страницу никто не комментировал. Вы можете стать первым.

Ваше имя:
Ваша почта:

RSS
Комментарий:
Введите символы или вычислите пример: *
captcha
Обновить





Хостинг на серверах в Украине, США и Германии. © sector.biz.ua 2006-2015 design by Vadim Popov