<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Работа для  программистов &#187; http</title>
	<atom:link href="http://job-interview.ru/articles/post/tag/http/feed" rel="self" type="application/rss+xml" />
	<link>http://job-interview.ru/articles</link>
	<description>вакансии, вопросы, статьи</description>
	<lastBuildDate>Thu, 29 Mar 2012 20:53:41 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Вопросы на собеседовании для PHP-программиста (часть 3)</title>
		<link>http://job-interview.ru/articles/post/104</link>
		<comments>http://job-interview.ru/articles/post/104#comments</comments>
		<pubDate>Sat, 01 Aug 2009 17:49:23 +0000</pubDate>
		<dc:creator></dc:creator>
				<category><![CDATA[Собеседования]]></category>
		<category><![CDATA[http]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[регулярные выражения]]></category>
		<category><![CDATA[собеседование]]></category>

		<guid isPermaLink="false">/articles/?p=104</guid>
		<description><![CDATA[Это заключительная статья, о вопросах на собеседованиях для PHP-программиста, на которые мне приходилось отвечать.
В первых двух статьях я уже выкладывал список вопросов.
В первой статье были вопросы по темам:

PHP
Задачи по составлению различных запросов SQL

В второй статье были вопросы по темам:

Администрирование MySQL
Основные принципы ООП

В этой статье я выкладываю вопросы с собеседований для PHP — программиста по следующим [...]]]></description>
			<content:encoded><![CDATA[<p>Это заключительная статья, о <strong>вопросах на собеседованиях</strong> для PHP-программиста, на которые мне приходилось отвечать.</p>
<p>В первых двух статьях я уже выкладывал список вопросов.</p>
<p>В первой <a title="Вопросы на собеседовании для PHP-программиста (часть 1)" href="/articles/post/12">статье</a> были вопросы по темам:</p>
<ul>
<li><em>PHP</em></li>
<li><em>Задачи по составлению различных запросов SQL</em></li>
</ul>
<p>В второй <a title="Вопросы на собеседовании для PHP-программиста (часть 2)" href="/articles/post/57">статье</a> были вопросы по темам:</p>
<ul>
<li><em>Администрирование MySQL</em></li>
<li><em>Основные принципы ООП</em></li>
</ul>
<p>В этой статье я выкладываю вопросы с собеседований для <strong>PHP — программиста</strong> по следующим темам:</p>
<ul>
<li><em>Регулярные выражения</em></li>
<li><em>Основные протоколы интернета</em></li>
<li><em>Работа в командной строке Linux</em></li>
</ul>
<p>Итак, представляю список вопросов.</p>
<h3>Регулярные выражения</h3>
<blockquote>
<ol>
<li>Напишите регулярное выражение для проверки E-mail.</li>
<li>С использованием регулярных выражений напишите скрипт, который в заданном тексте ищет все слова, начинающиеся на «Str», и переворачивает эти слова. На выходе скрипта должен быть текст с перевернутыми словами.</li>
<li>Напишите регулярное выражение, которое ищет все ссылки в документе HTML.</li>
</ol>
</blockquote>
<h3>Основные протоколы интернета</h3>
<blockquote>
<ol>
<li>По какому протоколу передаются данные в интернете?</li>
<li>Назовите <em>уровни модели OSI</em>.</li>
<li>В чем основные отличия протокола HTTP/1.1 от HTTP 1.0 ?</li>
<li>Что такое заголовки <em>HTTP</em>?</li>
<li>В чем состоит преимущество постоянных соединений?</li>
<li>Какие методы запроса протокола HTTP вы знаете?</li>
</ol>
</blockquote>
<h3>Работа в командной строке Linux</h3>
<blockquote>
<ol>
<li>Напишите команду, которая убьет все процессы, начинающиеся на «proc».</li>
<li>Напишите команду, которая поставит папке и всем папкам и файлам, которые в ней хранятся права: чтение, запись, выполнение для владельца, чтение, запись для группы, выполнение для всех остальных.</li>
<li>Какими средствами будете пользоваться, если нужно отслеживать запросы к web-серверу в реальном времени?</li>
</ol>
</blockquote>
<p>
На этом все. Надеюсь мой список вопросов поможет кому-то подготовиться к прохождению собеседования на должность PHP-программиста.
</p>
<p><a title="Вопросы на собеседовании для PHP-программиста (часть 1)" href="/articles/post/12">Вопросы на собеседовании для PHP-программиста (часть 1)</a></p>
<p><a title="Вопросы на собеседовании для PHP-программиста (часть 2)" href="/articles/post/57">Вопросы на собеседовании для php-программиста (часть 2)</a></p>
]]></content:encoded>
			<wfw:commentRss>http://job-interview.ru/articles/post/104/feed</wfw:commentRss>
		<slash:comments>451</slash:comments>
		</item>
		<item>
		<title>PHP и HTTP</title>
		<link>http://job-interview.ru/articles/post/86</link>
		<comments>http://job-interview.ru/articles/post/86#comments</comments>
		<pubDate>Mon, 27 Jul 2009 19:00:02 +0000</pubDate>
		<dc:creator></dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[http]]></category>
		<category><![CDATA[web]]></category>
		<category><![CDATA[программирование]]></category>

		<guid isPermaLink="false">/articles/?p=86</guid>
		<description><![CDATA[
В этой статье я постараюсь описать работу с HTTP-запросами в языке программирования PHP.


Очень часто на собеседованиях приходится слышать вопрос:

  Что происходит, когда пользователь в адресной строке браузера, вводит адрес сайта и нажимает enter?
  

Ответ должен звучать примерно так:


Отправляется HTTP-запрос по протоколу TCP/IP на сервер, на котором расположен сайт. Далее программа web-сервер (обычно Apache, [...]]]></description>
			<content:encoded><![CDATA[<p>
В этой статье я постараюсь описать работу с <strong>HTTP-запросами</strong> в языке программирования <strong>PHP</strong>.
</p>
<p>
Очень часто на <em>собеседованиях</em> приходится слышать вопрос:</p>
<blockquote><p>
  Что происходит, когда пользователь в адресной строке браузера, вводит адрес сайта и нажимает enter?
  </p></blockquote>
<p>
Ответ должен звучать примерно так:
</p>
<p>
Отправляется HTTP-запрос по протоколу <em>TCP/IP</em> на сервер, на котором расположен сайт. Далее программа web-сервер (обычно <em>Apache</em>, <em>nginx</em> или <em>lighttpd</em>) принимает этот запрос и в случае, если вызываемый файл — это обычный HTML, то посылает в ответ браузеру свой <strong>HTTP-ответ</strong>, в котором содержится этот <strong>HTML</strong>.
</p>
<p>
Если вызываемый файл — это скрипт, например PHP, то сначала передается управление этому скрипту, который после всех своих операций на выход подает HTML, который web-сервер отсылает HTTP-ответом обратно браузеру.
</p>
<p>
Получив от сервера HTML, браузер его преобразовывает в удобочитаемый вид согласно <a href="http://www.w3.org/" title="стандарт W3C">стандарту W3C</a>, отправляет дополнительные запросы для отображения изображений или flash и пользователь видит содержимое сайта — текст, картинки, flash и т.д.
</p>
<p>
В этой статье я дам подробное описание HTTP-запросов и параметров, которые могут в нем содержаться. Потом представлю реализацию обмена HTTP-запросами посредством языка PHP — мы напишем простой <strong>прокси-сервер</strong>, при обращении к которому он возвращает браузеру страницу сайта, адрес которого был указан в GET-параметре.
</p>
<p><span id="more-86"></span></p>
<p>
Для тех, кто не знает, браузеры обмениваются с серверами HTTP-запросами. Именно за счет этого мы можем переходить по ссылкам, отправлять данные формы и получать на эти действия ответы от сервера.
</p>
<p>
Кстати, очень полезными бывают утилиты, отображающие HTTP-запросы, которые отправляет и получает браузер. Я пользуюсь для этого браузером Mozilla Firefox и утилитой <a title="HttpFox" href="https://addons.mozilla.org/en-US/firefox/addon/6647">HttpFox</a>.
</p>
<p>
Итак, давайте рассмотрим пример.
</p>
<p>
Введем в адресную строку браузера <a href="http://example.com">http://example.com</a> и нажмем enter.
</p>
<p>
В результате браузер отправит HTTP-запрос вида:
</p>
<blockquote>
<pre>
GET / HTTP/1.1
Host: example.com
User-Agent: Mozilla/5.0 (X11; U; Linux i686; ru; rv:1.9.0.8) Gecko/2009032600 SUSE/3.0.8-1.1.1 Firefox/3.0.8
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: ru,en-us;q=0.7,en;q=0.3
Accept-Encoding: gzip,deflate
Accept-Charset: windows-1251,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive
</pre>
</blockquote>
<p>
В приведенном примере браузер хочет получить индексную страницу сайта example.com.
</p>
<p>
Получив запрос от браузера, web-сервер проверяет в своих настройках что является индексным файлом для сайта example.com.
</p>
<p>
Если это обычный HTML, например файл index.html, то просто возвращается его содержимое.
</p>
<p>При запросе индексной страницы сайта <a href="http://example.com">http://example.com</a> браузер получает от сервера следующий ответ:</p>
<blockquote>
<pre>
HTTP/1.x 200 OK
Date: Tue, 21 Jul 2009 17:09:54 GMT
Server: Apache/2.2.3 (CentOS)
Last-Modified: Tue, 15 Nov 2005 13:24:10 GMT
Etag: "b80f4-1b6-80bfd280"
Accept-Ranges: bytes
Content-Length: 438
Connection: close
Content-Type: text/html; charset=UTF-8 

&lt;HTML&gt;
&lt;HEAD&gt;
  &lt;TITLE&gt;Example Web Page&lt;/TITLE&gt;
&lt;/HEAD&gt;
&lt;body&gt;
&lt;p&gt;You have reached this web page by typing &quot;example.com&quot;,
&quot;example.net&quot;,
  or &quot;example.org&quot; into your web browser.&lt;/p&gt;
&lt;p&gt;These domain names are reserved for use in documentation and are not available
  for registration. See &lt;a href="http://www.rfc-editor.org/rfc/rfc2606.txt"&gt;RFC
  2606&lt;/a&gt;, Section 3.&lt;/p&gt;
&lt;/BODY&gt;
&lt;/HTML&gt;
</pre>
</blockquote>
<p>
Обратите внимание на <strong>2 перевода строки</strong> в ответе сервера. Они являются разделением между параметрами ответа и телом сообщения, содержащего html, который и отображается в окне браузера.
</p>
<p>
В случае какого-либо скрипта, сначала происходит выполнение этого скрипта, который возвращает web-серверу HTML. Web-сервер в свою очередь отправляет этот HTML браузеру.
</p>
<p>
Представим себе, что индексной страницей сайта example.com является файл index.php. Web-сервер в этом случае, получив запрос от браузера, сначала передает управление интерпретатору PHP, который выполняет код, содержащийся в этом файле.
</p>
<p>Например, в файле index.php содержался бы следующий код:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
	<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$GET</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'category'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">==</span> <span style="color: #cc66cc;">1</span><span style="color: #009900;">&#41;</span>
	<span style="color: #009900;">&#123;</span>
		<span style="color: #b1b100;">echo</span> <span style="color: #0000ff;">&quot;&lt;p&gt;This is a category of example.com&lt;/p&gt;&quot;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
	<span style="color: #b1b100;">else</span>
	<span style="color: #009900;">&#123;</span>
		<span style="color: #b1b100;">echo</span> <span style="color: #0000ff;">&quot;&lt;p&gt;This is a main page of example.com&lt;/p&gt;&quot;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></td></tr></table></div>

<p>
Если ввести в адресной строке браузера http://example.com?category=1 и нажать enter, то браузер отправит примерно следующий запрос:</p>
<blockquote>
<pre>
GET /index.php?category=1 HTTP/1.1
Host: example.com
User-Agent: Mozilla/5.0 (X11; U; Linux i686; ru; rv:1.9.0.8) Gecko/2009032600 SUSE/3.0.8-1.1.1 Firefox/3.0.8
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: ru,en-us;q=0.7,en;q=0.3
Accept-Encoding: gzip,deflate
Accept-Charset: windows-1251,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive
</pre>
</blockquote>
<p>
От сервера придет в этом случае следующий ответ:</p>
<blockquote>
<pre>
HTTP/1.x 200 OK
Date: Tue, 21 Jul 2009 17:09:54 GMT
Server: Apache/2.2.3 (CentOS)
Last-Modified: Tue, 15 Nov 2005 13:24:10 GMT
Etag: "b80f4-1b6-80bfd280"
Accept-Ranges: bytes
Content-Length: 39
Connection: close
Content-Type: text/html; charset=UTF-8 

&lt;p&gt;This is a category of example.com&lt;p&gt;</pre>
</blockquote>
<p>
Однако, если в адресной строке браузера ввести http://example.com/index.php, то ответ сервера будет таким: </p>
<blockquote><pre>
HTTP/1.x 200 OK
Date: Tue, 21 Jul 2009 17:09:54 GMT
Server: Apache/2.2.3 (CentOS)
Last-Modified: Tue, 15 Nov 2005 13:24:10 GMT
Etag: "b80f4-1b6-80bfd280"
Accept-Ranges: bytes
Content-Length: 40
Connection: close
Content-Type: text/html; charset=UTF-8 

&lt;p&gt;This is a main page of example.com&lt;/p&gt;
</pre>
</blockquote>
<p>
С телом запроса думаю все понятно — в нем содержится html, который и отражается в окне браузера. Давайте теперь разберем что же хранится в параметрах запроса браузера и ответа сервера.
</p>
<p>
Начнем с HTTP-запроса, который отправляет браузер.
</p>
<p>
Первая строка &#8211;  это строка запроса. Она содержит следующие поля, разделенные через пробел:</p>
<ul>
<li><strong>Метод запроса</strong>. Может принимать значения: OPTIONS, GET, HEAD, POST, DELETE, TRACE. Целью настоящей статьи не является рассмотрение всех методов. Нам будет достаточно метода GET. Если вы хотите получить описание каждого из методов, то советую обратится к документу <a href="http://www.faqs.org/rfcs/rfc2068.html" title="документ RFC 2068">RFC 2068</a></li>
<li><strong>Запрашиваемый URI</strong> — путь до запрашиваемого ресурса на сервере. Если запрашивается главная страница сайта, то указывается путь до корневого каталога сервера &#8211; «/».</li>
<li>Версия <strong>HTTP-протокола</strong>. В этом поле содержится строка вида: «HTTP/1.1». О различных версиях протокола HTTP также можно прочитать в документе <a href="http://www.faqs.org/rfcs/rfc2068.html" title="документ RFC 2086">RFC 2086</a>.</li>
</ul>
<p>
Далее после строки запроса следуют <strong>HTTP-заголовки</strong>. Описание каждого заголовка начинается с новой строки и представлено в виде:<br />
ЗАГОЛОВОК: ЗНАЧЕНИЕ.
</p>
<p>
Рассмотрим заголовки, которые отсылает браузер в нашем примере.</p>
<ul>
<li><strong>Host</strong>. Значением для этого заголовка должно быть доменное имя и порт запрашиваемого ресурса. Значение представляется в виде:
<p>ДОМЕННОЕ_ИМЯ:ПОРТ</p>
<p>Порт можно не указывать. В этом случае предполагается, что используется порт по умолчанию — в нашем случае это порт 80.</p>
<p>В нашем последнем примере для этого заголовка устанавливается значение example.com, т.е. браузер отправляет запрос на сервер example.com и хочет обратиться к файлу /index.php с переданным GET-параметром category=1.</p>
</li>
<li><strong>User-Agent</strong>. Содержит информацию о клиенте, который инициировал запрос к серверу, а также его программное обеспечение. Значение этого поля описывает ряд компонентов клиента. Оно может быть множественным, где все значения отделены друг от друга через пробел.
<p>В нашем последнем примере значением этого заголовка является:</p>
<p>Mozilla/5.0 (X11; U; Linux i686; ru; rv:1.9.0.8) Gecko/2009032600 SUSE/3.0.8-1.1.1 Firefox/3.0.8 </p>
<p>Здесь описываются параметры браузера и операционной системы — браузер Mozilla Firefox 3.0.8, основанный на движке Gecko, операционная система Linux Suse 11.1 оконной системой X11, процессор с архитектурой i686.</p>
<p>Этот заголовок используется для статистических целей.</p>
</li>
<li><strong>Accept</strong>. В этом заголовке клиент передает список форматов, которые допустимы для ответа. Значение этого поля хранит список допустимых форматов, разделенных через запятую. Кроме того, для каждого формата можно указать уровень предпочтения от 0 до 1. Если уровень предпочтения не указан, то он считается равным 1. Значение в этом поле должно соответствовать виду:
<p>ФОРМАТ1[;q=УРОВЕНЬ_ПРЕДПОЧТЕНИЯ1],ФОРМАТ2[;q=УРОВЕНЬ_ПРЕДПОЧТЕНИЯ2]&#8230;</p>
<p>В нашем примере браузер в этом заголовке посылает значение:</p>
<p>text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 </p>
<p>Его можно прочитать следующим образом: браузер предпочитает ответы в форматах text/html, application/xhtml+xml. Если сервер не может послать ответ в этих форматах, то браузер будет ожидать ответ в формате application/xml. Если же и в этом формате сервер не может послать ответ, то браузер примет ответ в любом формате.</p>
</li>
<li><strong>Accept-Language</strong>. Этот заголовок аналогичен заголовку ACCEPT, только здесь браузер сообщает серверу о своих предпочтениях о естественных языках, в которых должен приходить ответ.
<p>В нашем примере значением заголовка является:</p>
<p>ru,en-us;q=0.7,en;q=0.3 </p>
<p>Браузер сообщает серверу, что ждет ответ на русском языке, но также примет ответ на «американском английском» и английском языках.</p>
</li>
<li>
<strong>Accept-Encoding</strong>. Подобен ACCEPT. В этом заголовке браузер указывает какое кодирование к содержимому допустимо в ответе. Кодирование содержимого необходимо для сжатия или других его преобразований.
<p>В нашем примере в ответе для браузера допустимо сжатие программой gzip и механизмом deflate:</p>
<p>gzip,deflate</p>
</li>
<li><strong>Accept-Charset</strong>. Этот заголовок браузер посылает, чтобы сообщить серверу о своих предпочтениях кодировки ответа.
<p>В нашем примере этот заголовок принимает значение:</p>
<p>windows-1251,utf-8;q=0.7,*;q=0.7 </p>
<p>Браузер ждет ответ от сервера в первую очередь в кодировке windows-1251, но также примет ответ в любой кодировке.</p>
</li>
<li><strong>Keep-Alive</strong>. Заголовок Keep-Alive содержит значение, которое означает в течение какого времени в секундах будет удерживаться  соединение. Этот заголовок следует отправлять только в том случае, если заголовок Connection содержит значение keep-alive.
<p>Поддерживается только для протокола  HTTP версии 1.1.</p>
<p>В нашем примере этот заголовок содержит значение 300, т.е. браузер сообщает серверу, что намерен удерживать постоянное соединение с сервером в течение 300 секунд.</p>
</li>
<li>
<strong>Connection</strong>. Информация о проводимом соединении. В нашем примере этот заголовок принимает значение keep-alive, которое говорит серверу о том, что браузер хочет установить постоянное TCP соединение.
<p>До появления постоянных соединений для запроса каждой страницы сайта устанавливалось отдельное соединение. Открытие каждый раз отдельного соединения требует дополнительной нагрузки на сервер.</p>
<p>Например, браузер может запрашивать какую-то страницу с изображениями. После получения HTML страницы ему нужно будет запросить с сервера каждое изображение. При каждом запросе изображения будет открываться отдельное TCP соединение, что приведет к дополнительной нагрузке.</p>
<p>Использование постоянных соединений решает эту проблему. Если обе стороны (клиент и сервер) их поддерживают, то, в случае приведенного примера, HTML страницы и каждое изображение могут быть получены за одно TCP соединение.</p>
<p>Заголовок Connection поддерживается только для протокола  HTTP версии 1.1.</p>
<p>Этот заголовок также может принимать значение close. В этом случае клиент сообщит серверу, что после принятия HTTP-запроса соединение должно быть разорвано.</p>
</li>
</ul>
<p>
А теперь давайте рассмотрим параметры <strong>HTTP-ответа</strong>, который отправляет сервер браузеру.
</p>
<p>
Первая строка — это <strong>строка состояния</strong>, которая состоит из следующих полей, разделенных пробелом:
</p>
<ul>
<li><strong>Версия протокола HTTP</strong>. В нашем ответе от сервера в этом поле содержится HTTP/1.x. Сервер поддерживает протоколы HTTP 1.0 и 1.1.</li>
<li>Код состояния ответа. С возможными кодами состояния можно ознакомиться в документе <a href="http://www.faqs.org/rfcs/rfc2068.html" title="документ RFC 2068">RFC 2068</a>. В нашем случае от сервера нам необходим код состояния ответа, равный 200, который означат, что запрос браузера был выполнен удачно.</li>
<li><strong>Комментарий</strong>. Комментарий для кода состояния. Если код состояния 200, то комментарий будет «OK».</li>
</ul>
<p>
За строкой состояния следуют HTTP-заголовки, каждый начинается с новой строки. В нашем примере сервер отсылает следующие HTTP-заголовки:
</p>
<ul>
<li>
<p>
<strong>Date</strong>. В этом заголовке хранится дата в формате <a href="http://www.faqs.org/rfcs/rfc822.html" title="документ RFC 822">RFC 822</a>, описывающее когда отправляемый ответ был сгенерирован. Но это теория, на практике значением этого заголовка может быть любое время.
</p>
<p>В нашем примере в этом заголовке содержится:</p>
<p>Tue, 21 Jul 2009 17:09:54 GMT.</p>
</li>
<li>
<p>
<strong>Server</strong>. В этом заголовке содержится информация о программном обеспечении, которое используется на сервере, а также его компонентах. Если ответ от сервера направляется через proxy, то используется заголовок «Via».
</p>
<p>В ответе от сервере на наш запрос содержится следующее:</p>
<p>Apache/2.2.3 (CentOS)</p>
<p>Это означает, что на сервере используется web-сервер Apache версии 2.2.3. В качестве операционной системы используется дистрибутив Linux CentOS.</p>
</li>
<li>
<p>
<strong>Last-Modified</strong>. В этом заголовке сервер сообщает дату последнего изменения какой-либо сущности — файла, базы данных и т.п. В нашем случае сервер отправляет дату последнего изменения файла index.php.</p>
<p>Этот заголовок важен для браузера при использовании механизма кеширования. При обращении к какой-либо странице браузер кеширует ее. При повторном обращении к этой странице браузер, основываясь на заголовке Last-Modified проверит не устарела ли страница, сохраненная в кеше. Если нет, то браузер не будет еще раз считывать данные, а выведет страницу из кеша.</p>
<p>В ответе сервера из нашего примера в этом заголовке хранится:</p>
<p>Tue, 15 Nov 2005 13:24:10 GMT</p>
</li>
<li>
<p>
<strong>Etag</strong>. В этом заголовке содержится метка объекта ресурса. В нашем случае в качестве объекта выступает файл index.php.
</p>
<p>Наряду с заголовком Last-Modified значение этого заголовка используется при кешировании браузером. При первом запросе страницы браузер сохраняет значение Etag для страницы. При повторном запросе страницы значение Etag, которое пришло от сервера, сравнивается с тем, которое хранится в кеше браузера. Если они равны, то браузеру нет смысла считывать еще раз данные страницы, он просто возьмет их из кеша.</p>
<p>В нашем примере в ответе сервера Etag имеет следующее значение:</p>
<p>&#8220;b80f4-1b6-80bfd280&#8243;</p>
</li>
<li>
<p>
<strong>Accept-Ranges</strong>. Этот заголовок сообщает клиенту о том, что он может запрашивать данные с сервера фрагментами, указывая их смещение в байтах.
</p>
<p>Используется для реализации скачивания файлов с докачкой.</p>
<p>В нашем примере сервер поддерживает эту возможность, о чем он и сообщает, передав в заголовке Accept-Ranges значение bytes.</p>
<p>Зная эту возможность, браузер может передать серверу смещение в байтах, с которого необходимо начать передачу файла. Для этого браузер посылает заголовок Range с параметром bytes, значение которого и является смещением в байтах. Например:</p>
<p>Range: bytes=2048</p>
<p>Этот заголовок означает, что браузер запросил у сервера содержимое файла, начиная с 2-го мегабайта.</p>
</li>
<li>
<p>
Content-Length. Этот заголовок содержит размер тела HTTP-ответа сервера.<br />
В нашем примере размер тела сообщения 40.
</p>
</li>
<li>
<p>
<strong>Connection</strong>. Как и в случае для клиента, этот заголовок предоставляет информацию о проводимом соединении. В нашем примере этот заголовок принимает значение close, которое говорит клиенту о том, что сервер либо не поддерживает постоянное TCP соединение, либо он просто отказывает браузеру в постоянном соединении.
</p>
</li>
<li>
<p>
<strong>Content-Type</strong>. В этом заголовке содержится формат тела HTTP-ответа сервера.
</p>
<p>В нашем примере в этом заголовке содержится:</p>
<p>text/html; charset=UTF-8</p>
<p>Это означает, что сервер отвечает браузеру данными в формате text/html и кодировке UTF-8.</p>
<p>В этом заголовке сервера также может храниться, например, «text/css; charset=utf-8» при ответе браузеру на запрос файла CSS. Или, например, может храниться «image/gif» при ответе браузеру на запрос GIF-изображения.</p>
<p>О других форматах тела сообщения в ответах сервера читайте в <a href="http://www.faqs.org/rfcs/rfc822.html" title="документ RFC 822">RFC 822</a>.</p>
</li>
</ul>
<p>
После HTTP—заголовков в ответе сервера содержится 2 перевода строки, за которыми следует само тело сообщения. 2 перевода строки служат разделением между параметрами ответа сервера и телом сообщения, в котором содержится html, отображаемый браузером.
</p>
<p>
В нашем примере в теле сообщения ответа от сервера содержится:</p>
<blockquote><p>
  &lt;p&gt;This is a main page of example.com&lt;/p&gt;
  </p></blockquote>
<p>
Ну а теперь напишем простой <strong>прокси-сервер на PHP</strong>, который покажет практическое использование упомянутых HTTP-заголовков.
</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #000088;">$body</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;&quot;</span><span style="color: #339933;">;</span>
<span style="color: #666666; font-style: italic;">// доменное имя передаем в GET-параметре $_GET['host']</span>
<span style="color: #000088;">$host</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$_GET</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'host'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
<span style="color: #666666; font-style: italic;">// открываем сокет на стандартном для HTTP порту 80</span>
<span style="color: #000088;">$hSocket</span> <span style="color: #339933;">=</span> <span style="color: #990000;">fsockopen</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$host</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">80</span><span style="color: #339933;">,</span> <span style="color: #000088;">$errno</span><span style="color: #339933;">,</span> <span style="color: #000088;">$errstr</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">30</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> 
<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$hSocket</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #666666; font-style: italic;">// первой строкой идет строка запроса</span>
    <span style="color: #000088;">$request</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;GET / HTTP/1.1<span style="color: #000099; font-weight: bold;">\r</span><span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">;</span>
    <span style="color: #666666; font-style: italic;">// указываем доменное имя</span>
    <span style="color: #000088;">$request</span> <span style="color: #339933;">.=</span> <span style="color: #0000ff;">&quot;Host: <span style="color: #006699; font-weight: bold;">$host</span><span style="color: #000099; font-weight: bold;">\r</span><span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">;</span> 
     <span style="color: #666666; font-style: italic;">// пусть мы будем для сервера браузером Mozilla Firefox</span>
    <span style="color: #000088;">$request</span> <span style="color: #339933;">.=</span> <span style="color: #0000ff;">&quot;User-Agent: Mozilla/5.0 (X11; U; Linux i686; ru; rv:1.9.0.8) Gecko/2009032600 SUSE/3.0.8-1.1.1 Firefox/3.0.<span style="color: #000099; font-weight: bold;">\r</span><span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">;</span>
    <span style="color: #666666; font-style: italic;">// указываем форматы, в которых будем ожидать ответ от сервера</span>
    <span style="color: #000088;">$request</span> <span style="color: #339933;">.=</span> <span style="color: #0000ff;">&quot;Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8<span style="color: #000099; font-weight: bold;">\r</span><span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">;</span> 
    <span style="color: #666666; font-style: italic;">// языки, на которых ожидаем ответ</span>
    <span style="color: #000088;">$request</span> <span style="color: #339933;">.=</span> <span style="color: #0000ff;">&quot;Accept-Language: ru,en-us;q=0.7,en;q=0.3<span style="color: #000099; font-weight: bold;">\r</span><span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">;</span> 
    <span style="color: #666666; font-style: italic;">// указываем какое кодирование к содержимому допустимо в ответе. </span>
    <span style="color: #666666; font-style: italic;">//Только в этом случае нужно будет раскодировать содержимое.</span>
    <span style="color: #666666; font-style: italic;">//$request .= &quot;Accept-Encoding: gzip,deflate\r\n&quot;; </span>
    <span style="color: #666666; font-style: italic;">// выставляем предпочтения для кодировок ответа</span>
    <span style="color: #000088;">$request</span> <span style="color: #339933;">.=</span> <span style="color: #0000ff;">&quot;Accept-Charset: windows-1251,utf-8;q=0.7,*;q=0.7<span style="color: #000099; font-weight: bold;">\r</span><span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">;</span> 
    <span style="color: #666666; font-style: italic;">// будем удерживать постоянное соединение в течение 300 секунд</span>
    <span style="color: #000088;">$request</span> <span style="color: #339933;">.=</span> <span style="color: #0000ff;">&quot;Keep-Alive: 300<span style="color: #000099; font-weight: bold;">\r</span><span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">;</span>
    <span style="color: #666666; font-style: italic;">// открываем постоянное соединение</span>
    <span style="color: #666666; font-style: italic;">// здесь мы завершаем передачу HTTP-заголовков, </span>
    <span style="color: #666666; font-style: italic;">// поэтому в конце обязательно указываем 2 перевода строки</span>
    <span style="color: #000088;">$request</span> <span style="color: #339933;">.=</span> <span style="color: #0000ff;">&quot;Connection: keep-alive<span style="color: #000099; font-weight: bold;">\r</span><span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\r</span><span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">;</span> 
    <span style="color: #666666; font-style: italic;">// посылаем HTTP-заголовки через открытый сокет</span>
    <span style="color: #990000;">fwrite</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$hSocket</span><span style="color: #339933;">,</span> <span style="color: #000088;">$request</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> 
    <span style="color: #666666; font-style: italic;">// флаг, указывающий на то, что считывается тело запроса</span>
    <span style="color: #000088;">$bIsData</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #339933;">;</span> 
    <span style="color: #b1b100;">while</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #990000;">feof</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$hSocket</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #666666; font-style: italic;">// считываем ответ от сервера</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$str</span> <span style="color: #339933;">=</span> <span style="color: #990000;">fgets</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$hSocket</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">128</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// построчно</span>
        <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$bIsData</span><span style="color: #009900;">&#41;</span>
        <span style="color: #009900;">&#123;</span>
            <span style="color: #000088;">$body</span> <span style="color: #339933;">.=</span> <span style="color: #000088;">$str</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// тело запроса записываем в переменную $body</span>
        <span style="color: #009900;">&#125;</span>
        <span style="color: #666666; font-style: italic;">// встретилась строка, содержащая только перевод строки, это означает, </span>
        <span style="color: #666666; font-style: italic;">//что дальше пойдет тело запроса</span>
        <span style="color: #b1b100;">elseif</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$str</span> <span style="color: #339933;">==</span> <span style="color: #0000ff;">&quot;<span style="color: #000099; font-weight: bold;">\r</span><span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #009900;">&#41;</span> 
        <span style="color: #009900;">&#123;</span>
            <span style="color: #000088;">$bIsData</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #990000;">fclose</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$hSocket</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// закрываем сокет</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">// указываем на то, чтобы web-сервер отправил браузеру заголовки </span>
    <span style="color: #666666; font-style: italic;">// Last-Modified, Connection и Keep-alive</span>
    <span style="color: #990000;">header</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Last-Modified: Tue, 21 Jul 2009 17:09:54 GMT&quot;</span><span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #990000;">header</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Connection: Keep-Alive&quot;</span><span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">//</span>
    <span style="color: #990000;">header</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Keep-Alive: timeout=30, max=100&quot;</span><span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #666666; font-style: italic;">// передаем тело запроса</span>
    <span style="color: #b1b100;">echo</span> <span style="color: #000088;">$body</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// работа php-скрипта закончена, теперь web-сервер отправляет ответ браузеру</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></div></div>

<p>Чтобы отправить заголовки серверу, необходимо сначала открыть сокет. <strong>Сокет</strong> — это программный интерфейс, который позволяет обмениваться данными между процессами. При этом процессы могут выполняться на разных компьютерах, связанных сетью.
</p>
<p>
В нашем случае один процесс — это процесс браузера, второй — это процесс web-сервера, запущенный на удаленном компьютере.
</p>
<p>
В PHP сокет открывается функцией <a href="http://ru.php.net/fsockopen" title="функция PHP fsockopen">fsockopen</a>. Далее в переменную $request мы записываем все нужные нам заголовки и отправляем их серверу функцией <a href="http://ru.php.net/fwrite" title="функция PHP fwrite">fwrite</a>. После этого мы построчно считываем ответ сервера пока не будет достигнут конец данных (<a href="http://ru.php.net/feof" title="функция PHP feof">feof</a>). После получения ответа мы отправляем этот ответ браузеру вместе с заголовками, которые в PHP выставляются функцией <a href="http://ru.php.net/header" title="функция PHP header">header</a>.
</p>
<p>
Этот скрипт принимает через GET-параметр доменное имя сайта и отправляет к нему HTTP-запрос, считывает ответ и отдает этот ответ web-серверу, который отправляет его браузеру.
</p>
<p>
При помощи подобного скрипта вы можете сами поиграться с отправляемыми HTTP-запросами.
</p>
<p>
Нам этом все. Спасибо за внимание.
</p>
<p>
Для тех, кто заинтересовался и хочет подробнее изучить <strong>HTTP</strong> могу посоветовать следующие ссылки:
</p>
<p>
<a href="http://ru.wikipedia.org/wiki/HTTP" title="статья, подробно описывающая HTTP">http://ru.wikipedia.org/wiki/HTTP</a> &#8211; статья, подробно описывающая HTTP.
</p>
<p>
<a href="http://www.faqs.org/rfcs/rfc2068.html" title="документ RFC 2068">http://www.faqs.org/rfcs/rfc2068.html</a> &#8211; документ RFC 2068.</p>
]]></content:encoded>
			<wfw:commentRss>http://job-interview.ru/articles/post/86/feed</wfw:commentRss>
		<slash:comments>5539</slash:comments>
		</item>
	</channel>
</rss>
