Самостоятельное создание сайта
Самостоятельная раскрутка и продвижение сайта

Сокеты в php

   Когда говорят сокет, то часто представляют себе что-то абстрактное, и связанное с сетевыми изображение сокетапередачами. Но если выразится конкретнее, то получится что сокет, например, как протокол IP, это совокупность адреса (хоста) и порта. Адрес (хост) на текущий момент представляет из себя 32-x битный адрес. Наиболее часто его представляют в символьной форме mmm.nnn.ppp.qqq (адрес, разбитый на четыре октета по одному байту в октете и разделенный точками). Порт - это номер порта в диапазоне от нуля до 65535. Так вот, эта пара и есть сокет (гнездо в в котором расположены адрес и порт). В процессе обмена, как правило используются два сокета - сокет отправителя и сокет получателя.

   PHP позволяет скрипту соединиться с помощью сокетов к любому хосту и порту с помощью функции fsockopen. Функция fsockopen предназначена для соединения клиента с сервером. Она очень удобна, поскольку является универсальной и объединяет в себе те функции, которые есть в PHP для работы с сокетами.

   Что же делают сокеты? С помощью сетевых протоколов они обмениваются между собой запросами. Существуют такие виды сетевых протоколов:
   TCP - протокол управления передачей (Transmission Control Protocol).
   TCP/IP - (Transmission Control Protocol/Internet Protocol) - набор сетевых протоколов, позволяющих компьютерам (различных аппаратных платформ и с разными операционными системами) взаимодействовать по соединенным сетям и через Интернет. Любой компьютер в Интернете поддерживает tcp/ip. Это базовый протокол, используемый Internet.
   UDP - дополнительный компонент протокола tcp, поддерживающий выполняющуюся без подключений службу датаграмм, не гарантирующую ни доставку, ни правильную последовательность доставленных пакетов (аналогично протоколу ip).
   FTP - один из протоколов tcp/ip, используемый для копирования файлов с одного компьютера на другой через Интернет. При этом оба компьютера должны поддерживать соответствующие роли ftp: один должен быть клиентом ftp, а другой - сервером ftp.
   SSL - протокол, обеспечивающий защиту передаваемых данных с помощью шифров.
   TLS - стандартный протокол, используемый для обеспечения безопасности веб коммуникаций в Интернете и интрасетях. Позволяет клиентам проверять подлинность серверов или (необязательно) серверам проверять подлинность клиентов. Также обеспечивает безопасный канал за счет шифрования соединений. Протокол tls является самой последней и более безопасной версией протокола ssl.
   SMTP (Simple Mail Transfer Protocol) - что означает простой протокол передачи электронной почты;
   POP (Post Office Protocol) - почтовый протокол для приема электронной почты.

   В свою очередь в семействе TCP/IP существуют следующие протоколы:
   HTTP - (Hypertext Transfer Protocol) протокол прикладного уровня передачи данных в первую очередь в виде текстовых сообщений. Основой http является технология «клиент-сервер», то есть клиенты посылают запрос, а серверы, которые ожидают соединения для получения запроса, производят необходимые действия и возвращают обратно сообщение с результатом. Порт сервера по умолчанию 80 или 8080.
   HTTPS - расширение протокола http, поддерживающее шифрование. Https не является отдельным протоколом. По сути это обычный http, работающий через шифрованные транспортные механизмы ssl и tls. Порт сервера по умолчанию 443.

   Давайте теперь еще раз определим, что такое сокеты с точки зрения интернета. Распространенным протоколом передачи информации между клиентами (веб браузеры, например Internet Explorer, Mozilla Firefox, Opera, Google Chrome и др.) и серверами (удаленные сайты) является HTTP.
   Принцип работы протокола HTTP - обмен текстовыми запросами (сообщениями). Таким образом, сокеты позволяют отправить на определенный хост (адрес) и номер порта текстовое сообщение, а в ответ получить другое текстовое сообщение.

   Теперь необходимо разобраться, что это за текстовое сообщение и из чего оно состоит. Я не буду описывать всю спецификацию протокола HTTP. Просто посмотрим на пример обмена http заголовками между браузером и сервером.

------------------------------------------

Запрос клиента:
GET /index.php HTTP/1.1
Host: master-web.com.ua
User-Agent: Mozilla/5.0 (X11; U; Linux i686; ru; rv:1.9b5) Gecko/2008050509 Firefox/3.0b5
Accept: text/html
Connection: close

------------------------------------------

Ответ сервера:
HTTP/1.0 200 OK
Date: Wed, 11 Feb 2009 11:20:59 GMT
Server: Apache
X-Powered-By: PHP/5.2.4-2ubuntu5wm1
Last-Modified: Wed, 11 Feb 2009 11:20:59 GMT
Content-Language: ru
Content-Type: text/html; charset=utf-8
Content-Length: 1234
Connection: close

(далее следует код запрошенной страница в HTML)

------------------------------------------

   Запрос клиента начинается с команды GET. Каждый сервер должен поддерживать как минимум две команды GET и HEAD. Посмотрите какие еще существуют основные команды:
   GET - используется для запроса содержимого указанного ресурса (страницы). В результате этой команды сервер должен выполнить запрос и возвратить ответ. Как правило, все клиенты (браузеры) для получения страницы сайта по url используют get.
   HEAD - аналогичен методу GET, за исключением того, что в ответе сервера отсутствует тело. Другими словами обратно Вы получите только заголовок ответа сервера, но не код страницы.
   POST - применяется для передачи пользовательских данных заданному ресурсу. Эти данные могут быть в виде файла или просто текста. Как правило, название переменной и ее значение.
   TRACE - возвращает полученный запрос так, что клиент может увидеть, что промежуточные сервера добавляют или изменяют в запросе.

   Разбираем запрос клиента дальше.
   После команды серверу идет часть URI запроса относительно хоста. Например, в данном случае мы запрашиваем содержимое страницы index.php, которая находится в корневом каталоге хоста. Но мы также, можем запросить и такой URI: /info/price.php?type=1 и он будет прекрасно работать.
   Далее, в первой строке запроса клиента следует указание вида протокола, в данном случае он указан как HTTP/1.1 (может быть и HTTP/1.0 и HTTP/0.9), но обычно используют HTTP/1.0.
   В строке (Host:) указывается название хоста к которому мы отправляем http-запрос.
В строке (User-Agent:) указывается название клиента (в данном случае одна из версий браузера Mozilla).
   В строке (Accept:) указываем в каком формате мы хотим получить данные.
   В строке (Connection:) мы закрываем соединение. Это является правилом хорошего тона, так как сервер при обращении к нему создает отдельное соединение, которое обслуживает все дальнейшие Ваши запросы. Однако, если его не закрыть ничего не случится, сервер закроет его сам, но через определенный промежуток времени.

   Кроме вышеперечисленных строк, существует еще множество других параметров которые можно указать в запросе, но перечислять все нет смысла, Вы можете сами посмотреть вживую на обмен http-запросами между клиент-сервером, например, с помощью дополнительной утилиты (надстройки) к Mozilla Firefox "Tamper Data". Более детально запрос клиента мы еще разберем ниже.

   Теперь рассмотрим ответ сервера. Первая строка ответа начинается с указания типа http-протокола, в данном случае это HTTP/1.0. Далее идет статус (код) ответа сервера. Посмотрите на таблицу с диапазонами ответов сервера:

Диапазон кодов Значение ответа
100–199 Информационный
200–299 Запрос клиента успешен
300–399 Запрос клиента переадресован, необходимы дальнейшие действия
400–499 Запрос клиента является неполным
500–599 Ошибки сервера

Список популярных ответов сервера:

Код Значение ответа
200 Запрошенный документ найден и сейчас будет выслан.
301, 302 Запрошенный документ навсегда перенесен в другое расположение. При этом в поле Location будет указано новое расположение документа.
401 Запрошенный документ присутствует, однако для его получения требуется авторизация на сервере.
402 Запрошенный документ (страница) не найден на сервере.
500 Произошла внутренняя ошибка сервера. Как правило, такие ошибки возникают при коллизиях между CGI-программой и сервером.

В нашем примере код ответа сервера имеет значение 200 OK. Это означает, что указанная в клиент-запросе страница найдена и ответ успешно возвращается. Последующие строчки, я думаю, Вам должны быть понятны интуитивно.

   Что ж, мы сделали краткое вступление к понятию сокетов в php и теперь можем смело приступить к написанию нашего сокета в php.
   Как я уже выше писал, для создания сокетов в php используется функция fsockopen. Посмотрите на этот код:

<?php

$fp = fsockopen("master-web.com.ua", 80, $errno, $errstr, 30);
if (!$fp) {
      echo "$errstr ($errno)
";
} else {
      $query = "GET / HTTP/1.1 ";
      $query .= "Host: master-web.com.ua ";
      $query .= "Connection: Close ";
      fwrite($fp, $query);
      $page = '';
      while (!feof($fp)) {
         $page .= fgets($fp, 4096);
      }
   fclose($fp);
   if (!empty($page)) echo '<pre>'.$page.'</pre>';

?>

   Выполните этот код на своем web сервере и Вы получите корневую страницу с хоста master-web.com.ua, а также заголовок ответа сервера.

   Функция fsockopen имеет следующие параметры:
   "master-web.com.ua" - название домена, к которому осуществляется подключение, можно, также, указать ip-адрес (например, "62.149.26.133");
   80 - адрес порта удаленного сервера, к которому подключаемся;
   $errno - в случае ошибки соединения в эту переменную заносится номер ошибки;
   $errstr - в случае ошибки соединения в эту переменную заносится текстовое объяснение ошибки;
   30 - время в миллисекундах на протяжении которого будут осуществляется попытки соединится или timeout по истечении которого попытки соединения будут прекращены.
   Функция fwrite($fp, $query) - отправляет запрос $query и записывает ответ в файловый поток $fp.
   Функция fgets($fp, 4096) - считывает построчно содержимое файловый поток $fp.

   В результате удачного соединения (открытия сокета) переменная $fp обретает значение и мы отправляем текстовый запрос к серверу. Составить правильный текстовый запрос к серверу очень важно, поэтому я детально постараюсь его описать.
   Запрос клиента может состоять из пары строк, а может и из десятка строк. Все зависит специфики запроса и того, что Вы сами хотите сообщить серверу. Каждая строка (кроме первой) состоит из параметра и его значения разделенные двоеточием :, например, Host: master-web.com.ua , Referer: http://google.com/ , Cookie: income=1 и т.д.
   В конце строки в обязательном порядке должен быть код переноса строки " ". Часто пишут " ", где " " - перенос строки, а " " - перевод каретки в начало строки. Весь http-заголовок заканчивается двойным переносом строки, например Connection: Close или просто User-Agent: Mozilla/5.0 (compatible; MSIE 6.0; Windows 98) .
   Спросите: зачем необходим двойной перенос строки? Во-первых, согласно спецификации HTTP, двойной перенос означает окончание http-запроса, а во-вторых, вспомните, что POST передача подразумевает передачу все данных не в строке запроса (в виде ..index.php?var1=1&var2=2), а внутри http-запроса:

$query = "POST /e/19 HTTP/1.1 ";
$query .= "Host: master-web.com.ua ";
$query .= "Accept-Language: ru ";
$query .= "Expires: Thu, 01 Jan 1970 00:00:01 GMT ";
$query .= "Connection: Close ";
$query .= "var1=1&var2=2";

   Как двойной перенос строки " " отделяет http-запрос от переменных, так он и отделяет http-ответ сервера от содержимого страницы. Благодаря этому клиенты (браузера) выводят на экран страницу без заголовка ответа.

   Перечень параметров, которые могут передаваться серверу:
   Accept
   Пример: Accept: text/html, text/plain, image/gif, image/jpeg
   Эта строка используется клиентом, что сказать серверу, какие типы данных он воспринимает. На основе этого заголовка создается переменная окружения HTTP_ACCEPT_ENCODING.
   Accept-Encoding
   
Пример: Accept-Encoding: bzip2, gzip
   Определяет типы сжатия, с которыми может работать наш браузер/скрипт, и которые желательно использовать при передаче документа (если сервер поддерживает данные форматы сжатия).
   Accept-Language
   Пример: Accept-Language: ru,en-us;q=0.7,en;q=0.3
   Означает, какая раскладка клавиатуры у нас установлена и на каком языке должен возвращаться запрошенный документ.
   Accept-Charset
   Пример: Accept-Charset: koi8-r;q=1.0, iso-8859-5;q=0.9, iso-8859-1;q=0.1
   Определяет кодировки, с которыми может работать наш браузер/скрипт, и которые желательно использовать при передаче документа.
   Cookie
   Пример: Cookie: var1=1;var2=2;type=blob;
   Передача cookie, на основе этого заголовка создается глобальный массив $_COOKIE.
   Content-length
   Пример: Content-length: 1001
   Длина данных в байтах, переданных после двух переносов строки. Актуально при передачи данных методом POST или когда сервер отвечает на запрос. Размер переданных данных должен быть обязательно равен этому значению, иначе сервер ничего не будет выполнять, так как посчитает, что получил неполный пакет данных. На основе этого заголовка создается переменная окружения $ _SERVER["CONTENT_LENGTH"].
   Content-Type
   Пример: Content-Type: text/html;charset=ISO-8859-4
   Тип данных, которые передаются в теле запроса. Поле Content-Type не имеет значения по умолчанию.
   Keep-Alive
   Пример: Keep-Alive: 300
   Определяет время в секундах, в течение которого данное соединение с сервером должно удерживаться (не должно разрываться).
   Referer
   Пример: Referer: info-pages.com.ua
   URL страницы, с которой клиент перешел на данную страницу. На основе этого параметра создается переменная окружения $_SERVER["HTTP_REFERER"].
   User-Agent
   Пример: User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)
   Строка, описывающая браузер и ОС. На основе этого заголовка создается переменная окружения $_SERVER["HTTP_USER_AGENT"].

   Теперь Вы можете полноценно обмениваться http-сообщениями с любым сервером, используя сокеты. При этом Вы можете послать ему любое значение одного из заголовков. Например, если Вы включаете в запрос http-заголовок "User-Agent: Opera/7.23 (Windows 98; U) [en]", то сервер будет думать что у Вас установлена Windows 98 и работаете Вы под Operо'й. А если вы укажите такой заголовок "Referer: google.com", то сервер решит, что Вы пришли из Гугл страницы.

   Меняя значение заголовков в http-запросах, Вы можете указывать серверу любые параметры. И тогда единственным способом Вашей идентификации в интернете, будет Ваш ip-адрес. Однако в интернете, также существуют и анонимные прокси-серверы, которые могут скрывать реальный ip-адрес. Благодаря этим небольшим хитростям Вы можете посылать http-запросы на прокси-сервер, предварительно конечно проверив его анонимность, и на 99% быть уверенными, что идентифицировать Вас будет задачей довольно сложной.
   Но, я думаю, Вы найдете более полезное применение сокетов на практике и создадите, например какой-нибудь полезный скрипт для авторизации на форумах, или почтовых сервисах передавая серверу необходимые данные.

1579
3.9 60
Рейтинг: +3.9 , голосов 60
Вы еще не голосовали!
Добавить комментарий (комментариев: 8)
Удалить ответ

Ваш почтовый ящик никогда не будет опубликован
Трудно разобрать цифры? Нажмите на рисунок, чтобы обновить.
#1 03/06/2014 11:41 max
reply
Статья отличная!
#2 23/03/2012 11:15 Павел
reply
статья очень хорошая... у меня такой вопрос а капчу спомощью сокетов тоже можно обходить или я все перепутал?
#3 21/05/2010 23:26 ZEOS
reply
Если автор статьи будет не против за ссылки, то выкладываю ссылку на сервис http://h.zeos.in/ , который я сделал благодаря этой статье. Именно тут я понял как это работает :) А в этом сервисе можно посылать своему серверу любые заголовки Фсем спасибо
#4 13/05/2010 08:27 iZet
reply
СУПЕР СУПЕР СУПЕР. Везде тока описание фукции fsockopen(), а нормального толкового как тут объяснения я ваще нигде не нашол. Афтар - вечная тебе жизнь за это и по больше интузиазма к написанию еще таких же статей. Вобщем РЕСПЕКТ!!!!
#5 06/05/2010 19:02 ZEOS
reply
Спасибо большое! Классная статья :)
#6 01/09/2009 20:25 neron
reply
Статья - бомба! Автору спасибо!
#7 26/04/2009 17:41 Алексей
reply
Помогите пожайлуста на локальном сервере, установленном на домашний компьютер в системе windows не работает функция fsockopen() то есть не подключается серверу сайта, подскажите как включить данную функцию, какие параметры нужно раскоментировать в php.ini
27/04/2009 18:21 admin
в php.ini необходимо раскомментировать extension=php_sockets.dll, также проверьте с помощью функции phpinfo(); включенность сокетов в разделе sockets

Дополнительно

» С чего начать сайт?

» Установка программ

» Пример создания сайта

» Хостинг и домен

» Оптимизация сайта

» Раскрутка сайта

» Заработок web-мастера

» Примеры PHP/Javascript

» Блог и мои записки

Последние новости

Статьи по рейтингу

» Особенности покупки контента 5.0 1
» Выбор хостинга 4.8 5
» Поисковые системы 4.7 9
» Курс молодого web-мастера 4.6 21
» Где взять бесплатные ссылки 4.5 11
» Что такое сниппеты 4.5 6
» Addstudio - SEO модуль 4.5 4
» Отладка js и CSS 4.4 14
» Стратегия дохода на Sape.ru 4.3 3
» Каталоги и биржи статей 4.3 4