Сокеты и http протокол. |
Здравствуйте, гость ( Вход | Регистрация )
Сокеты и http протокол. |
Jan 25 2007, 01:28
Сообщение
#1
|
|
Личное звание Группа: Admins Сообщений: 328 Регистрация: 11.6.2006 Пользователь №: 2980 |
Надеюсь вы уже знакомы с зачатками мирк скриптинга. =)
Итак, чтобы как-то взаимодействовать с сервером нам нужно создать сокет, сгенерировать запрос, получить ответ. Все очень легко=) Сокет обращается к серверу, а не к странице, или к файлу, который вы хотите скачать. При его создании нужно указать хост или IP сервера и порт, по которому вы соединяетесь с сервером (ибо существуют не только http протокол, да и сервер можно настроить так, что работать он будет не по стандартному http порту) Итак начнем. ЧАСТЬ 1. Открытие сокета и отправка запроса. Для начала нам нужно как-то обозвать сокет, чтобы отличать его от других, которые возможно будут работать одновременно с ним.=) Например назовем его test. %socet = test Стандартный http порт - (IMG:http://forum.iseekyou.im/style_emoticons/default/mega_shok.gif) й %port = (IMG:http://forum.iseekyou.im/style_emoticons/default/mega_shok.gif) Так же нам понадобится сервер, с которым мы соединяемся (запомните, хост пишется без http:// иногда без www, иногда с ним, смотря как сервер настроен) %host = google.ru Создаем (открываем) сокет sockopen %socet %host %port Итак сокет открыт. Генерируется событие SOCKOPEN. Обрабатываем его. on *:SOCKOPEN:test:{ Теперь по плану мы должны сформировать запрос. Он сотоит из строк; в первой мы должны указать, по какому методу будет обрабатываться наш запрос, что мы хотим закачать с сервера, и с какой версией протокола HTTP мы работаем. Выглядит это так: METHOD %path HTTP/1.0 Где %path - локальный путь до файла, относительно хоста. Т.е. если полная ссылка до файла или страницы - http://www.google.ru/images/hp1.gif , то соответственно %path = /images/hp1.gif Естественно %path надо определять до запроса=) HTTP 1.0 мы взяли, потому что нам не важно сейчас, какая версия протокола=) Основных методов два: GET и POST Различия между ними в том, что в методе GET основным параметром является запрос файла или страницы, и данные скрипту мы можем передавать только в этой строке (для тех кто не до конца понял, это %path) Соответствено %path может выглядеть так: /aaa.php?param1=word1¶m2=word2 Скрипт aaa.php обработает param1, значением которого является word1 и param2, значением соответственно является word2 В методе POST данные передаются не через строку запроса, а отдельно (мы это рассмотрим ниже). 1я строка запроса у нас должна соответственно выглядеть примерно так: GET %path HTTP/1.0 или вместо GET - POST Остальные строки запроса, это сведения о нас Выглядят они так Параметр: Значение В конце должны стоять символы перехода на новую строку ($clrf) Основной параметр: Host - хост откуда берем, мы по нему соединялись. Все остальные параметры необязательные, но все же посмотрим основные (по моему мнению) =) Referer - место откуда мы якобы пришли=) Cookie - куки, которые мы якобы получили на этом сайте. В методе GET последняя строка Параметр: значение, должна оканчиваться на $clrf 2 раза (первод строки, и еще раз перевод строки) Для метода POST у нас добавляется еще параметр Content-Length - количество пересылаемых данных в байтах Content-Length оканчивается на $clrf 2 раза, но потом идут передаваемые данные, в общем виде выглядящие так: param1=word1¶m2=word2 эти данные должны иметь размер равный указанному в Content-Length =) Т.е. буквально то же самое что мы передаем в методе GET в 1й строке. В чем различие? В методе POST можно передавать большие объемы данных ~300кбайт, если я не ошибаюсь=) Метод GET работает всегда, можете передавать ссылку кому хотите, скрипт обработает как надо=) Все параметры запроса (а их много) вы можете посмотреть в RFC1945 - HTTP/1.0 Specification Для того, чтобы запрос записать в сокет, будем использовать команду /sockwrite -n %socet Запись построчно -n - Добавление символов перевода строки если их еще нет Так же можем воспользоваться индетефикатором $sockname - возвращает имя сокета (вместо %socet). $sockerr - если у нас есть ошибка, > 0. По значению можно узнать, что у нас за ошибка. ИТОГ 1й ЧАСТИ Объявляем переменные %host,%path,%port (думаю справитесь) Потом открываем сокет sockopen test %host %port Посылаем запрос. on *:SOCKOPEN:test:{ if ($sockerr > 0) { echo -a Error1 | return } sockwrite -n $sockname GET %path HTTP/1.0 sockwrite -n $sockname Host: %host $str($crlf,2) } $str($crlf,2) - 2 раза перевели на следущую строку (закрыли запрос). Способов много, но мне так больше нравится=) ЧАСТЬ 2 Принимаем данные. После отправки запроса ждем ответа=) Ответ состоит из 2х частей: 1) Служебный ответ сервера. После него идет пустая строка 2) То, что мы хотим получить Служебный ответ состоит из нескольких строк: 1я строка, состоит из версии протокола и кода, который сообщает нам правильно ли мы постучались, а так же состояние файла=) HTTP/1.0 200 Кодов много, в RFC они есть, а так же во многих местах подробно описаны Основные 200 - документ есть, все в порядке 404 - всем известный код: Документ не найден. Здесь внизу можете посмотреть краткую расшифровку кодов (на английском) Остальными строками сервер сообщает клиенту о себе, а также например тип файла. Но это нам сейчас неважно. Если захотите узнать больше, RFC вас ждет=) Итак при приеме данных генерируется событие SOCKREAD За прием данных отвечает команда sockread, при чем она может записывать данные как в обычную переменную, так и в бинарную =) Примем например все в обычную переменную и запишем в файл. %filename - название файла. on *:SOCKREAD:test: { if ($sockerr > 0) { echo -a Error2 | return } sockread %tmp write %filename %tmp %tmp = $null } Здесь есть несколько недостатков (если нам нужно просто скачать файл): 1) у нас сохраняется все, включая служебный ответ сервера 2) принятая строка может быть слишком длинная, и функция write выдаст ошибку, и не запишет в файл 3) если мы принимаем не текст, то сохранить так скорей всего не получится Поэтому избавляемся от них. Порассуждаем Очевидно мы должны сохранять в бинарную переменную. Убираются недостаток 2 и 3, но надо отделить служебный ответ сервера. тут вспоминаем, что между ним и основным текстом пустые строки, для этого проверяем на длину принимаемой строки. Пока не найдем пустую... Возьмем значение длины строки например 4. Все равно сначала у нас идут строки явно больше 4х символов=) Объявляем где-нибудь раньше в программе, переменную например %chek = 0 on *:SOCKREAD:test: { if ($sockerr > 0) { echo -a Error2 | return } if (%check == 0) { sockread %tmp if ($len(%tmp) (IMG:http://forum.iseekyou.im/style_emoticons/default/mega_shok.gif) %path = /images/hp0.gif %filename = hp0.gif .remove %filename sockopen test %host %port } on *:SOCKOPEN:test:{ %check = 0 if ($sockerr > 0) { echo -a Error1 | return } sockwrite -n $sockname GET %path HTTP/1.0 sockwrite $sockname Host: %host $str($crlf,2) } on *:SOCKREAD:test: { if ($sockerr > 0) { echo -a Error2 | return } if (%check == 0) { sockread %tmp if ($len(%tmp) < 4) { %check = 1 } } if (%check == 1) { sockread &binvar bwrite %filename -1 -1 &binvar } } on *:SOCKCLOSE:test: { echo -a Complete! } Просто наберите /http_test и проверьте =) Проверено в mIRC 6.12, ошибок нет, все скачивается нормально remove - чтобы файл не дописывался в конец существующего, если запустите несколько раз. Эта статья не претендует на большую правильность. =) Просто надеюсь, что кому-то помог. Если заинтересовались, читаете хелп по мирку в разделе сокеты и RFC по http протоколу (а так же по другим ). Я освятил далеко не все возможности Удачи вам=) |
|
|
Текстовая версия | Сейчас: 29th December 2024 - 03:27 |