<?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>Melnaron</title>
	<atom:link href="http://melnaron.net/feed" rel="self" type="application/rss+xml" />
	<link>http://melnaron.net</link>
	<description>Серьёзная веб-разработка</description>
	<lastBuildDate>Tue, 31 Jan 2012 09:01:37 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Правильный запуск PHP-скриптов в бекграунде</title>
		<link>http://melnaron.net/development/proper-way-to-execute-php-script-in-background</link>
		<comments>http://melnaron.net/development/proper-way-to-execute-php-script-in-background#comments</comments>
		<pubDate>Tue, 31 Jan 2012 09:01:37 +0000</pubDate>
		<dc:creator>Melnaron</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Hints]]></category>
		<category><![CDATA[Command line]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://melnaron.net/?p=425</guid>
		<description><![CDATA[Переодически при разработке различных проектов перед нашей командой встает задача запуска PHP-скрипта в бекграунде для выполнения каких-либо действий, будь то какое-то длительное импортирование или граббинг чего-либо с переодическим оповещением о статусе процесса. И каждый раз после пробного выполнения команды вроде &#8220;$ php -q script.php > script.log &#038;&#8221; мы получаем то, что скрипт перестает выполняться сразу [...]]]></description>
			<content:encoded><![CDATA[<p>Переодически при разработке различных проектов перед нашей командой встает задача запуска PHP-скрипта в бекграунде для выполнения каких-либо действий, будь то какое-то длительное импортирование или граббинг чего-либо с переодическим оповещением о статусе процесса. И каждый раз после пробного выполнения команды вроде &#8220;$ php -q script.php > script.log &#038;&#8221; мы получаем то, что скрипт перестает выполняться сразу же после запуска: &#8220;[1]+ Stopped php -q script.php > script.log&#8221;.</p>
<p>Причиной тому является <a href="http://www.php.net/manual/ru/features.connection-handling.php" target="_blank">определенное поведение</a> PHP-интерпритатора когда он теряет связь с запустившим его клиентом, а в данном случае — с вводом командной строки.</p>
<p>Если изучить PHP-документацию по <a href="http://www.php.net/manual/ru/features.connection-handling.php" target="_blank">работе с соединениями</a>, то оттуда можно узнать что таким поведением можно управлять при помощи директивы конфигурации или же функции вызываемой непосредственно в самом PHP-скрипте — <a href="http://php.net/manual/ru/function.ignore-user-abort.php" target="_blank">ignore_user_abort</a>. Таким образом, по идее, остановка выполнения PHP-скрипта после отсоединения клиента не должна происходить если включить игнорирование отсоединения клиента, но мы, к сожалению, не смогли добиться нужного поведения при использовании этой директивы или функции и PHP-скрипты запускаемые в бекграунде продолжали &#8220;умирать&#8221; сразу же после запуска.</p>
<p>Сейчас уже эта проблема конечно же не вызывает ни ступора, ни поисков нужной информации, но в свое время &#8220;съела&#8221; несколько часов на поиск нужного решения и проверку/отладку найденного способа, поэтому я хочу во-первых поделиться со всеми читателями данным трюком, а во-вторых — написав этот пост и освежив тем самым в памяти способ решения данной проблемы еще лучше запомнить его на будущее когда опять нужно будет вспомнить как же правильно запускать PHP-скрипты в бекграунде <img src='http://melnaron.net/wordpress/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p>Итак, решение очень простое — нужно дать PHP-скрипту то, что ему нужно — поток ввода, который он будет считать клиентом и не будет завершать свою работу:</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">$ php -q script.php &lt; /dev/null &gt; script.log &amp;</div></td></tr></tbody></table></div>
<p>После запуска подобной команды PHP-скрипт не &#8220;умрет&#8221; сразу же после запуска, а продолжит запланированную работу до тех пор пока ее не выполнит!</p>
<p>Надеюсь что этот небольшой хинт поможет кому-то сэкономить пару часов! <img src='http://melnaron.net/wordpress/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://melnaron.net/development/proper-way-to-execute-php-script-in-background/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Как изменить {baseURL} для поиска по-умолчанию в Google Chrome</title>
		<link>http://melnaron.net/hints/how-to-change-baseurl-for-google-chrome-default-search-engine</link>
		<comments>http://melnaron.net/hints/how-to-change-baseurl-for-google-chrome-default-search-engine#comments</comments>
		<pubDate>Tue, 29 Nov 2011 18:27:25 +0000</pubDate>
		<dc:creator>Melnaron</dc:creator>
				<category><![CDATA[Hints]]></category>
		<category><![CDATA[baseURL]]></category>
		<category><![CDATA[Google Chrome]]></category>
		<category><![CDATA[Search Engines]]></category>

		<guid isPermaLink="false">http://melnaron.net/?p=414</guid>
		<description><![CDATA[Простое решение для изменения поиска по умолчанию в Google Chrome с локального (например, через google.ru) на глобальный (через google.com) с поддержкой HTTPS при помощи редактирования внутренней переменной baseURL.]]></description>
			<content:encoded><![CDATA[<p>Если вы установили браузер Google Chrome и начали что-то искать через omnibox находясь при этом например в России, то скорее всего при первом поисковом запросе baseURL установится на http://www.google.ru/, и все ваши поисковые запросы будут открываться именно через google.ru.</p>
<p>Многие хотят использовать по умолчанию google.com (да и еще через https) и как же это сделать?!</p>
<p><span id="more-414"></span></p>
<p>Немного по-google-ив можно найти простые решения вроде тех что советуют просто создать новый Search Engine, в котором в поле для ввода URL вместо {google:baseURL} нужно указать www.google.com, но это скорее компромис нежели решение данной проблемы.</p>
<p>А нормальное решение данной проблемы следующее:</p>
<ol>
<li>Закрываем Google Chrome и проверяем чтобы выгрузились все его процессы (если же какие-нибудь процессы продолжают висеть, то их нужно убить например при помощи killall или другой подручной утилиты);</li>
<li>Открываем любым текстовым редактором файл &#8220;/Users/username/Library/Application Support/Google/Chrome/Local State&#8221; (для Mac OS) или же &#8220;C:\Users\username\AppData\Local\Google\Chrome\User Data\Local State&#8221; (для Windows 7), где &#8220;username&#8221; это имя вашего пользователя в системе;</li>
<li>Видим структуру конфигурационного файла в формате JSON и находим следующие параметры: &#8220;last_known_google_url&#8221; и &#8220;last_prompted_google_url&#8221;;</li>
<li>Меняем значения этих параметров на &#8220;https://www.google.com/&#8221;;</li>
<li>Сохраняем файл и запускаем Google Chrome.</li>
</ol>
<p>Скорее всего Google Chrome после первого поискового запроса через omnibox попытается предложить вам опять использовать google.ru, но мы этот запрос отклоняем выбирая &#8220;Keep using google.com&#8221; и наслаждаемся поиском в гугле через google.com + https.</p>
]]></content:encoded>
			<wfw:commentRss>http://melnaron.net/hints/how-to-change-baseurl-for-google-chrome-default-search-engine/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Content Assist для jQuery в Eclipse</title>
		<link>http://melnaron.net/development/content-assist-%d0%b4%d0%bb%d1%8f-jquery-%d0%b2-eclipse</link>
		<comments>http://melnaron.net/development/content-assist-%d0%b4%d0%bb%d1%8f-jquery-%d0%b2-eclipse#comments</comments>
		<pubDate>Sat, 29 Oct 2011 17:53:11 +0000</pubDate>
		<dc:creator>Melnaron</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Eclipse]]></category>
		<category><![CDATA[jQuery]]></category>

		<guid isPermaLink="false">http://melnaron.net/?p=408</guid>
		<description><![CDATA[Если в своих проектах вы используете библиотеку jQuery и работаете в такой популярной IDE как Eclipse, то вам, видимо как и нам, точно должно нехватать удобного Content Assist&#8217;а для просмотра и подстановки нужных jQuery-методов. И почему команда jQuery не выпустит специальную неминимизированную версию с нормальными комментариями к методам в формате JSDoc?! Скорее всего у них, [...]]]></description>
			<content:encoded><![CDATA[<p>Если в своих проектах вы используете библиотеку jQuery и работаете в такой популярной IDE как Eclipse, то вам, видимо как и нам, точно должно нехватать удобного Content Assist&#8217;а для просмотра и подстановки нужных jQuery-методов. И почему команда jQuery не выпустит специальную неминимизированную версию с нормальными комментариями к методам в формате JSDoc?! Скорее всего у них, так же как и у нас, очень много работы, и тратить свое время на написание специального файла покрывающего документацией весь функционал всех методов jQuery они не могут. А мы в свою очередь иногда не можем (не хотим) позволить себе просматривать документацию в поисках нужного метода. И тут нам поможет Content Assist для JavaScript в Eclipse&#8230;</p>
<p><span id="more-408"></span></p>
<p>Что нужно для того чтобы научить Content Assist показывать все методы jQuery после ввода $(&#8230;).| или после $.|: нужно найти специально сформированный JSDoc-файл который покрывает все методы jQuery комментариями со специальным форматированием в которых указаны все параметры методов с типами, а так же возможно простые примеры использования того или иного метода.</p>
<p>Скачать подобного рода файлы можно например <a href="http://code.google.com/p/jquery-jsdoc/downloads/list" target="_blank">отсюда</a> или же <a href="http://code.google.com/p/closure-compiler/source/browse/trunk/contrib/externs/jquery-1.6.js" target="_blank">отсюда</a>. К сожалению первый файл достаточно старый и покрывает только методы jQuery версии 1.3, а вот второй уже ориентирован на версию 1.6, но на счет его полноты у нас есть некоторые сомнения.</p>
<p>Далее установка. В Eclipse открываем настройки: Window -> Preferences, в открывшемся окне настроек идем в ветку JavaScript -> Include Path -> User Libraries, добавляем новую библиотеку например с именем jQuery и в ней добавляем один из скачанных выше файлов. Готово, осталось немного настроить нужный нам проект на поддержку Content Assist&#8217;ом добавленной только что библиотеки. Для этого открываем свойства нужного проекта и идем в ветку JavaScript -> Include Path, где на вкладке Libraries добавляем созданную нами User Library. Все. Теперь в JS-файлах можно будет пользоваться Content Assist&#8217;ом на предмет автодополнения jQuery-методов!</p>
]]></content:encoded>
			<wfw:commentRss>http://melnaron.net/development/content-assist-%d0%b4%d0%bb%d1%8f-jquery-%d0%b2-eclipse/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Функция &#8220;вырезать&#8221; в Finder на Mac OS</title>
		<link>http://melnaron.net/macos/%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d1%8f-%d0%b2%d1%8b%d1%80%d0%b5%d0%b7%d0%b0%d1%82%d1%8c-%d0%b2-finder-%d0%bd%d0%b0-mac-os</link>
		<comments>http://melnaron.net/macos/%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d1%8f-%d0%b2%d1%8b%d1%80%d0%b5%d0%b7%d0%b0%d1%82%d1%8c-%d0%b2-finder-%d0%bd%d0%b0-mac-os#comments</comments>
		<pubDate>Tue, 11 Oct 2011 07:30:02 +0000</pubDate>
		<dc:creator>Melnaron</dc:creator>
				<category><![CDATA[Mac OS]]></category>
		<category><![CDATA[Usability]]></category>

		<guid isPermaLink="false">http://melnaron.net/?p=396</guid>
		<description><![CDATA[Странно что Apple не реализовала в своем файловом менеджере Finder функцию &#8220;Cut&#8221; (&#8220;Вырезать&#8221;) для файлов в привычном для нее смысле. Хотя если раскрыть ниспадающее меню &#8220;Edit&#8221; при выделенных файлах, то там красуется неактивный пункт &#8220;Cut (Cmd+X)&#8221; &#8211; зачем он там? Правильно! Вырезать кусочки текста при редактировании имен файлов! Но никак не для перемещения файлов. Получается [...]]]></description>
			<content:encoded><![CDATA[<p>Странно что Apple не реализовала в своем <strong>файловом</strong> менеджере Finder функцию &#8220;Cut&#8221; (&#8220;Вырезать&#8221;) <strong>для файлов</strong> в привычном для нее смысле. Хотя если раскрыть ниспадающее меню &#8220;Edit&#8221; при выделенных файлах, то там красуется неактивный пункт &#8220;Cut (Cmd+X)&#8221; &#8211; зачем он там? Правильно! Вырезать кусочки текста при редактировании имен файлов! Но никак не для перемещения файлов. Получается некоторая дискриминация для тех кто предпочитает использовать клавиатуру для работы с файловыми массивами по средством Finder&#8217;а, так как Apple пропагандирует повсеместное использование Drag&#038;Drop для перемещения файлов.</p>
<p>Далее я хочу рассказать о простом решении данной проблемы несколькими способами&#8230;</p>
<p><span id="more-396"></span></p>
<p>Если немного по-Google-ть, то обнаруживаются старые посты про то, что &#8220;нехитрой&#8221; командой в терминале</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">defaults write com.apple.finder AllowCutForItems 1</div></td></tr></tbody></table></div>
<p>можно включить &#8220;Cut&#8221; для файлов, но в комментариях пишут что &#8220;вырезание&#8221; файла перемещает его в корзину или что-то в этом роде (проверить не удалось так как, судя по словам негодующих на эту тему, работает это только в 10.3).</p>
<p>Так же в некоторых постах пишут предположения (факты?) почему Apple так поступила с &#8220;Cut&#8221;:</p>
<blockquote><p>
Почему же Apple считает, что вырезание файлов – опасная штука? Объяснений тут два:</p>
<ul>
<li>вы можете вырезать файл, забыть о нём и перезагрузить систему, потеряв его навсегда,</li>
<li>вы можете случайно несколько раз вырезать разные файлы, безвозвратно затерев предыдущие.</li>
</ul>
</blockquote>
<p>Зачем вырезая файл куда-то его перемещать? Ведь в том же терминале приспокойно работает команда</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">mv source_path destination_path</div></td></tr></tbody></table></div>
<p>и в функции &#8220;Cut&#8221; можно было бы как минимум использовать простое копирование в буфер обмена полного пути (source_path) файла со специальным маркером обозначающим что при выполнении вставки будет происходить фактически выполнение команды mv в директорию назначения (destination_path) в которой мы выполняем &#8220;Paste&#8221; (&#8220;Вставить&#8221;).</p>
<p>Ну что же, мысль не плохая, но нужно будет поколдовать чуть больше (что как раз возможно породит еще один пост на эту тему с другим готовым решением), а сейчас пока что более простое решение&#8230;</p>
<p>Идея проста, мы создаем сервис в Automator&#8217;е, которому назначаем сочетание горячих клавиш и который в свою очередь принимает выделенные в Finder&#8217;е файлы или директории как входной параметр, открывает диалог выбора директории назначения после чего перемещает выбранные файлы/директории в выбранное место.</p>
<p>Итак, открываем в Automator&#8217;е диалог создания нового Service&#8217;а и добавляем первое действие &#8220;Get Selected Finder Items&#8221;, это позволит нам получить все выделенные файлы и директории в активном окне Finder&#8217;а. Далее добавляем действие &#8220;Run AppleScript&#8221; со следующим содержанием:</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">on run {input, parameters}<br />
&nbsp; &nbsp;activate<br />
&nbsp; &nbsp;set theFolder to choose folder with prompt &quot;Select destination folder&quot; without invisibles<br />
&nbsp; &nbsp;tell application &quot;Finder&quot; to move input to theFolder<br />
&nbsp; &nbsp;activate application &quot;Finder&quot;<br />
&nbsp; &nbsp;return input<br />
end run</div></td></tr></tbody></table></div>
<p>Все. Сохраняем сервис например под именем &#8220;Smart Move&#8221;, назначаем ему сочетание горячих клавиш и проверяем его работу в Finder&#8217;е!</p>
<p>Данное решение немного доработано по сравнению с подобными, которые можно найти на других блогах, в плане перевода фокуса вначале на открывающийся диалог выбора директории назначения, а потом обратно на окно Finder&#8217;а.</p>
<p>P.S. В конце концов, когда идея написания этого поста уже была записана где-то в блокноте, я нашел-таки аналог функции &#8220;вырезать&#8221; в Finder для Mac OS Lion – сначала копируем файл (Cmd+C), а затем вставляем, удалив оригинал (Cmd+Opt+V). Wow! Разработчики сподобились добавить хотя бы такой &#8220;костыль&#8221;!</p>
]]></content:encoded>
			<wfw:commentRss>http://melnaron.net/macos/%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d1%8f-%d0%b2%d1%8b%d1%80%d0%b5%d0%b7%d0%b0%d1%82%d1%8c-%d0%b2-finder-%d0%bd%d0%b0-mac-os/feed</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Ускорение Eclipse на OS X 10.6 Snow Leopard</title>
		<link>http://melnaron.net/tools/speed-up-eclipse-on-os-x-10-6-snow-leopard</link>
		<comments>http://melnaron.net/tools/speed-up-eclipse-on-os-x-10-6-snow-leopard#comments</comments>
		<pubDate>Tue, 17 May 2011 12:37:20 +0000</pubDate>
		<dc:creator>Melnaron</dc:creator>
				<category><![CDATA[Tools]]></category>
		<category><![CDATA[Eclipse]]></category>
		<category><![CDATA[Mac OS]]></category>

		<guid isPermaLink="false">http://melnaron.net/?p=391</guid>
		<description><![CDATA[Как говорится в этой статье нужно немного отредактировать eclipse.ini который лежит в пакете Eclipse.app. Изменить нужно всего 3 строчки: 123-Xms40m -Xmx384m -Dosgi.requiredJavaVersion=1.5 следующим образом: 123-Xms80m -Xmx768m -Dosgi.requiredJavaVersion=1.6 удвоив значения для выделяемой памяти -Xms и -Xmx, и изменив требуемую версию Java-машины с 1.5 на 1.6 (Java 1.6 должна быть установлена, проверить можно командой “java -version” в [...]]]></description>
			<content:encoded><![CDATA[<p>Как говорится в <a href="http://www.inteist.com/2010/05/how-to-speed-up-eclipse-on-os-x-10-6-snow-leopard/">этой статье</a> нужно немного отредактировать eclipse.ini который лежит в пакете Eclipse.app.</p>
<p>Изменить нужно всего 3 строчки:</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">-Xms40m<br />
-Xmx384m<br />
-Dosgi.requiredJavaVersion=1.5</div></td></tr></tbody></table></div>
<p>следующим образом:</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">-Xms80m<br />
-Xmx768m<br />
-Dosgi.requiredJavaVersion=1.6</div></td></tr></tbody></table></div>
<p>удвоив значения для выделяемой памяти -Xms и -Xmx, и изменив требуемую версию Java-машины с 1.5 на 1.6 (Java 1.6 должна быть установлена, проверить можно командой “java -version” в терминале).</p>
<p>Так же возможно это поможет ускорить Eclipse на Windows-платформах (мой Эклипс на Win7 помоему стал немного шустрее по откликам в интерфейсе).</p>
]]></content:encoded>
			<wfw:commentRss>http://melnaron.net/tools/speed-up-eclipse-on-os-x-10-6-snow-leopard/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PHP: Получение первого элемента возвращаемого массива в одну строчку</title>
		<link>http://melnaron.net/development/php-get-first-element-of-returned-array-in-single-line</link>
		<comments>http://melnaron.net/development/php-get-first-element-of-returned-array-in-single-line#comments</comments>
		<pubDate>Sat, 14 May 2011 18:03:35 +0000</pubDate>
		<dc:creator>Melnaron</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://melnaron.net/?p=383</guid>
		<description><![CDATA[Многие разработчики которые работают одновременно и с PHP и с JavaScript знают как в JS легко получить первый (и, скорее всего, единственный) элемент массива возвращенного функцией и сразу же использовать его: 1var body = document.getElementsByTagName&#40;'body'&#41;&#91;0&#93;; Но, скорее всего, немногие знают, что в PHP можно делать так же: получать первый элемент возвращаемого функцией массива в одной [...]]]></description>
			<content:encoded><![CDATA[<p>Многие разработчики которые работают одновременно и с PHP и с JavaScript знают как в JS легко получить первый (и, скорее всего, единственный) элемент массива возвращенного функцией и сразу же использовать его:</p>
<div class="codecolorer-container javascript default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #003366; font-weight: bold;">var</span> body <span style="color: #339933;">=</span> document.<span style="color: #660066;">getElementsByTagName</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'body'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#91;</span><span style="color: #CC0000;">0</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span></div></td></tr></tbody></table></div>
<p>Но, скорее всего, немногие знают, что в PHP можно делать так же: получать первый элемент возвращаемого функцией массива в одной строчке:</p>
<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000088;">$first_tag</span> <span style="color: #339933;">=</span> <span style="color: #990000;">current</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$post</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getTags</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></td></tr></tbody></table></div>
<p>Функция <a href="http://ru.php.net/manual/ru/function.current.php">current()</a> возвращает элемент на котором в данный момент установлен внутренний указатель массива.</p>
]]></content:encoded>
			<wfw:commentRss>http://melnaron.net/development/php-get-first-element-of-returned-array-in-single-line/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Запрет вызова контекстного меню браузера при помощи jQuery</title>
		<link>http://melnaron.net/development/disable-browser-context-menu-with-jquery</link>
		<comments>http://melnaron.net/development/disable-browser-context-menu-with-jquery#comments</comments>
		<pubDate>Thu, 12 May 2011 18:19:53 +0000</pubDate>
		<dc:creator>Melnaron</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[Mouse Event]]></category>

		<guid isPermaLink="false">http://melnaron.net/?p=354</guid>
		<description><![CDATA[Допустим у нас есть изображение при правом клике мыши на которое вы не хотите чтобы отображалось контекстное меню браузера, или же вы хотите отобразить свое контекстное меню для какого-то элемента на странице&#8230; Для отлова события при клике на элемент правой кнопкой мыши есть параметр &#8220;oncontextmenu&#8221;: 1&#60;img src=&#34;...&#34; oncontextmenu=&#34;return false;&#34;/&#62; Код &#8220;return false;&#8221;, который выполняется при [...]]]></description>
			<content:encoded><![CDATA[<p>Допустим у нас есть изображение при правом клике мыши на которое вы не хотите чтобы отображалось контекстное меню браузера, или же вы хотите отобразить свое контекстное меню для какого-то элемента на странице&#8230;</p>
<p>Для отлова события при клике на элемент правой кнопкой мыши есть параметр &#8220;oncontextmenu&#8221;:</p>
<div class="codecolorer-container html4strict default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="html4strict codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">img</span> <span style="color: #000066;">src</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;...&quot;</span> oncontextmenu<span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;return false;&quot;</span><span style="color: #66cc66;">/</span>&gt;</span></div></td></tr></tbody></table></div>
<p>Код &#8220;return false;&#8221;, который выполняется при наступлении этого события в примере выше, приводит к тому что контекстное меню не показывается. Тут так же можно разместить вызов любого вашего метода для отображения вашего контекстного меню&#8230;</p>
<p><span id="more-354"></span></p>
<p>Но что если возможности добраться напрямую к html-коду того или иного элемента у вас нет? Например в одном из наших проектов нужно было запретить контекстное меню при клике правой кнопкой на всплывающем просмотрщике изображений <a href="http://fancybox.net/">Fancybox</a>. Конечно же ковырять и изменять подключаемую библиотеку не хотелось и было найдено очень простое и в то же время действенное решение: назначение обработчика события &#8220;oncontextmenu&#8221; при наступлении события &#8220;mousedown&#8221;&#8230;</p>
<div class="codecolorer-container javascript default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br /></div></td><td><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">$<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'#fancybox-wrap'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">delegate</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'#fancybox-outer'</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'mousedown'</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>e<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>e.<span style="color: #660066;">which</span> <span style="color: #339933;">==</span> <span style="color: #CC0000;">3</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; $<span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#91;</span><span style="color: #CC0000;">0</span><span style="color: #009900;">&#93;</span>.<span style="color: #660066;">oncontextmenu</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #003366; font-weight: bold;">false</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></td></tr></tbody></table></div>
<p>e.which в данном случае содержит код кнопки мыши которая была нажата: 1 &#8211; левая, 2 &#8211; средняя, 3 &#8211; правая. jQuery в данном случае унифицирует коды именно так, потому что в разных браузерах они немного отличаются друг от друга. Например в IE коды нативные коды 1, 4, 2 соответственно.</p>
<p>Таким образом мы легко можем поймать событие клика правой кнопкой мыши на любом элементе веб-страницы, запретить отображение контекстного меню браузера и, например, отобразить над этим элементом свое контекстное меню.</p>
<p>Данный код проверен и работает в следующих браузерах которые оказались под рукой: Google&nbsp;Chrome&nbsp;11, Internet&nbsp;Explorer&nbsp;9, Firefox&nbsp;4, Opera&nbsp;11, Safari&nbsp;5.</p>
]]></content:encoded>
			<wfw:commentRss>http://melnaron.net/development/disable-browser-context-menu-with-jquery/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Китайские карты в 3D поражают воображение</title>
		<link>http://melnaron.net/web/%d0%ba%d0%b8%d1%82%d0%b0%d0%b9%d1%81%d0%ba%d0%b8%d0%b5-%d0%ba%d0%b0%d1%80%d1%82%d1%8b-%d0%b2-3d-%d0%bf%d0%be%d1%80%d0%b0%d0%b6%d0%b0%d1%8e%d1%82-%d0%b2%d0%be%d0%be%d0%b1%d1%80%d0%b0%d0%b6%d0%b5%d0%bd</link>
		<comments>http://melnaron.net/web/%d0%ba%d0%b8%d1%82%d0%b0%d0%b9%d1%81%d0%ba%d0%b8%d0%b5-%d0%ba%d0%b0%d1%80%d1%82%d1%8b-%d0%b2-3d-%d0%bf%d0%be%d1%80%d0%b0%d0%b6%d0%b0%d1%8e%d1%82-%d0%b2%d0%be%d0%be%d0%b1%d1%80%d0%b0%d0%b6%d0%b5%d0%bd#comments</comments>
		<pubDate>Wed, 02 Jun 2010 10:24:03 +0000</pubDate>
		<dc:creator>Melnaron</dc:creator>
				<category><![CDATA[Web]]></category>
		<category><![CDATA[Amazing Web]]></category>
		<category><![CDATA[Maps]]></category>

		<guid isPermaLink="false">http://melnaron.net/?p=311</guid>
		<description><![CDATA[Недавно в своем Google Reader&#8217;е я наткнулся на интересную запись о том, что китайцы начали рисовать карты своих городов в 3D! Отрисовано уже несколько десятков городов, и, скажу я вам, детализация просто поражает воображение! Прямо SimCity какой-то! Побродить по картам &#8220;вживую&#8221; можно тут: http://sh.o.cn/, http://www.o.cn/, http://gz.o.cn/, http://www.jc08.com/. Если вам нехватает понимания китайских иероглифов, то советую [...]]]></description>
			<content:encoded><![CDATA[<p>Недавно в своем <a href="http://www.google.com/reader/shared/melnaron">Google Reader&#8217;е</a> я наткнулся на <a href="http://mezarkabul.livejournal.com/71582.html">интересную запись</a> о том, что китайцы начали рисовать карты своих городов в 3D! Отрисовано уже несколько десятков городов, и, скажу я вам, детализация просто поражает воображение!</p>

<a href='http://melnaron.net/web/%d0%ba%d0%b8%d1%82%d0%b0%d0%b9%d1%81%d0%ba%d0%b8%d0%b5-%d0%ba%d0%b0%d1%80%d1%82%d1%8b-%d0%b2-3d-%d0%bf%d0%be%d1%80%d0%b0%d0%b6%d0%b0%d1%8e%d1%82-%d0%b2%d0%be%d0%be%d0%b1%d1%80%d0%b0%d0%b6%d0%b5%d0%bd/attachment/cn_map-1' title='cn_map (1)'><img width="150" height="150" src="http://melnaron.net/wordpress/wp-content/uploads/2010/06/cn_map-1-150x150.jpg" class="attachment-thumbnail" alt="cn_map (1)" title="cn_map (1)" /></a>
<a href='http://melnaron.net/web/%d0%ba%d0%b8%d1%82%d0%b0%d0%b9%d1%81%d0%ba%d0%b8%d0%b5-%d0%ba%d0%b0%d1%80%d1%82%d1%8b-%d0%b2-3d-%d0%bf%d0%be%d1%80%d0%b0%d0%b6%d0%b0%d1%8e%d1%82-%d0%b2%d0%be%d0%be%d0%b1%d1%80%d0%b0%d0%b6%d0%b5%d0%bd/attachment/cn_map-2' title='cn_map (2)'><img width="150" height="150" src="http://melnaron.net/wordpress/wp-content/uploads/2010/06/cn_map-2-150x150.jpg" class="attachment-thumbnail" alt="cn_map (2)" title="cn_map (2)" /></a>
<a href='http://melnaron.net/web/%d0%ba%d0%b8%d1%82%d0%b0%d0%b9%d1%81%d0%ba%d0%b8%d0%b5-%d0%ba%d0%b0%d1%80%d1%82%d1%8b-%d0%b2-3d-%d0%bf%d0%be%d1%80%d0%b0%d0%b6%d0%b0%d1%8e%d1%82-%d0%b2%d0%be%d0%be%d0%b1%d1%80%d0%b0%d0%b6%d0%b5%d0%bd/attachment/cn_map-3' title='cn_map (3)'><img width="150" height="150" src="http://melnaron.net/wordpress/wp-content/uploads/2010/06/cn_map-3-150x150.jpg" class="attachment-thumbnail" alt="cn_map (3)" title="cn_map (3)" /></a>
<a href='http://melnaron.net/web/%d0%ba%d0%b8%d1%82%d0%b0%d0%b9%d1%81%d0%ba%d0%b8%d0%b5-%d0%ba%d0%b0%d1%80%d1%82%d1%8b-%d0%b2-3d-%d0%bf%d0%be%d1%80%d0%b0%d0%b6%d0%b0%d1%8e%d1%82-%d0%b2%d0%be%d0%be%d0%b1%d1%80%d0%b0%d0%b6%d0%b5%d0%bd/attachment/cn_map-4' title='cn_map (4)'><img width="150" height="150" src="http://melnaron.net/wordpress/wp-content/uploads/2010/06/cn_map-4-150x150.jpg" class="attachment-thumbnail" alt="cn_map (4)" title="cn_map (4)" /></a>
<a href='http://melnaron.net/web/%d0%ba%d0%b8%d1%82%d0%b0%d0%b9%d1%81%d0%ba%d0%b8%d0%b5-%d0%ba%d0%b0%d1%80%d1%82%d1%8b-%d0%b2-3d-%d0%bf%d0%be%d1%80%d0%b0%d0%b6%d0%b0%d1%8e%d1%82-%d0%b2%d0%be%d0%be%d0%b1%d1%80%d0%b0%d0%b6%d0%b5%d0%bd/attachment/cn_map-5' title='cn_map (5)'><img width="150" height="150" src="http://melnaron.net/wordpress/wp-content/uploads/2010/06/cn_map-5-150x150.jpg" class="attachment-thumbnail" alt="cn_map (5)" title="cn_map (5)" /></a>
<a href='http://melnaron.net/web/%d0%ba%d0%b8%d1%82%d0%b0%d0%b9%d1%81%d0%ba%d0%b8%d0%b5-%d0%ba%d0%b0%d1%80%d1%82%d1%8b-%d0%b2-3d-%d0%bf%d0%be%d1%80%d0%b0%d0%b6%d0%b0%d1%8e%d1%82-%d0%b2%d0%be%d0%be%d0%b1%d1%80%d0%b0%d0%b6%d0%b5%d0%bd/attachment/cn_map-6' title='cn_map (6)'><img width="150" height="150" src="http://melnaron.net/wordpress/wp-content/uploads/2010/06/cn_map-6-150x150.jpg" class="attachment-thumbnail" alt="cn_map (6)" title="cn_map (6)" /></a>
<a href='http://melnaron.net/web/%d0%ba%d0%b8%d1%82%d0%b0%d0%b9%d1%81%d0%ba%d0%b8%d0%b5-%d0%ba%d0%b0%d1%80%d1%82%d1%8b-%d0%b2-3d-%d0%bf%d0%be%d1%80%d0%b0%d0%b6%d0%b0%d1%8e%d1%82-%d0%b2%d0%be%d0%be%d0%b1%d1%80%d0%b0%d0%b6%d0%b5%d0%bd/attachment/cn_map-7' title='cn_map (7)'><img width="150" height="150" src="http://melnaron.net/wordpress/wp-content/uploads/2010/06/cn_map-7-150x150.jpg" class="attachment-thumbnail" alt="cn_map (7)" title="cn_map (7)" /></a>
<a href='http://melnaron.net/web/%d0%ba%d0%b8%d1%82%d0%b0%d0%b9%d1%81%d0%ba%d0%b8%d0%b5-%d0%ba%d0%b0%d1%80%d1%82%d1%8b-%d0%b2-3d-%d0%bf%d0%be%d1%80%d0%b0%d0%b6%d0%b0%d1%8e%d1%82-%d0%b2%d0%be%d0%be%d0%b1%d1%80%d0%b0%d0%b6%d0%b5%d0%bd/attachment/cn_map-8' title='cn_map (8)'><img width="150" height="150" src="http://melnaron.net/wordpress/wp-content/uploads/2010/06/cn_map-8-150x150.jpg" class="attachment-thumbnail" alt="cn_map (8)" title="cn_map (8)" /></a>

<p>Прямо SimCity какой-то!</p>
<p>Побродить по картам &#8220;вживую&#8221; можно тут: <a href="http://sh.o.cn/">http://sh.o.cn/</a>, <a href="http://www.o.cn/">http://www.o.cn/</a>, <a href="http://gz.o.cn/">http://gz.o.cn/</a>, <a href="http://www.jc08.com/">http://www.jc08.com/</a>.</p>
<p>Если вам нехватает понимания китайских иероглифов, то советую вам установить <a href="http://www.google.com/chrome">Google Chrome</a> &#8211; он в автоматическом режиме предлагает перевести страници на ваш язык.</p>
]]></content:encoded>
			<wfw:commentRss>http://melnaron.net/web/%d0%ba%d0%b8%d1%82%d0%b0%d0%b9%d1%81%d0%ba%d0%b8%d0%b5-%d0%ba%d0%b0%d1%80%d1%82%d1%8b-%d0%b2-3d-%d0%bf%d0%be%d1%80%d0%b0%d0%b6%d0%b0%d1%8e%d1%82-%d0%b2%d0%be%d0%be%d0%b1%d1%80%d0%b0%d0%b6%d0%b5%d0%bd/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Peer-to-Peer Chat in Flash</title>
		<link>http://melnaron.net/development/peer-to-peer-chat-in-flash</link>
		<comments>http://melnaron.net/development/peer-to-peer-chat-in-flash#comments</comments>
		<pubDate>Sun, 30 May 2010 18:40:45 +0000</pubDate>
		<dc:creator>Melnaron</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Flash]]></category>
		<category><![CDATA[Flex]]></category>
		<category><![CDATA[P2P]]></category>
		<category><![CDATA[Stratus]]></category>

		<guid isPermaLink="false">http://melnaron.net/?p=261</guid>
		<description><![CDATA[peer-to-peer p2p chat in flash with adobe stratus service]]></description>
			<content:encoded><![CDATA[<p>Этой статьей я хочу открыть новую тему в своем блоге, посвященную разработке на Flash/Flex/ActionScript3. Итак приступим.</p>
<h3>Flash Player 10.0</h3>
<p>Начиная с версии 10.0 во Flash Player появилась очень интересная возможность, которая позволяет устанавливать прямые соединения между плеерами при помощи сервиса <a href="http://labs.adobe.com/technologies/stratus/" target="_blank">Stratus</a>:</p>
<div class="codecolorer-container actionscript default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br /></div></td><td><div class="actionscript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">nc = <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #0066CC;">NetConnection</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;<br />
nc.<span style="color: #006600;">addEventListener</span><span style="color: #66cc66;">&#40;</span>NetStatusEvent.<span style="color: #006600;">NET_STATUS</span>, netStatusHandler<span style="color: #66cc66;">&#41;</span>;<br />
nc.<span style="color: #0066CC;">connect</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'rtmfp://stratus.adobe.com/YOUR_DEVELOPER_KEY_HERE'</span><span style="color: #66cc66;">&#41;</span>;</div></td></tr></tbody></table></div>
<p>Этот сервис выполняет роль организатора: подключившись к нему ваш клиент получает уникальный Peer ID, зная который, другие такие же как и вы клиенты, могут напрямую подключаться к вашему клиенту и подписываться на данные, которые вы публикуете. </p>
<p>Давайте рассмотрим эту схему более подробно, по шагам:</p>
<ul>
<li>Flash-клиент в вашем браузере соединяется с сервисом <a href="http://labs.adobe.com/technologies/stratus/" target="_blank">Stratus</a></li>
<li>В клиенте создается поток (NetStream), в который начинается публикация какого-то контента</li>
<li>Другие flash-клиенты также соединяются с сервисом <a href="http://labs.adobe.com/technologies/stratus/" target="_blank">Stratus</a></li>
<li>В них создаются потоки, которые подключаются к вашему клиенту по его Peer ID и подписываются на контент от него</li>
</ul>
<p>Это самая простая схема: один клиент публикует контент, а другие подписываются на получение контента.</p>
<p>Но давайте попробуем усложнить эту схему. Что если каждый клиент и публикует и подписывается на потоки всех известных ему клиентов?</p>
<p><span id="more-261"></span></p>
<h3>Чат</h3>
<p>Сейчас я много занимаюсь разработкой приложений для коммуникации. Это и аудио/видео чаты, и обычные текстовые чаты (кто-нибудь помнит мой Mel.Chat?). И в связи с этим я хочу поделиться небольшим примером разработки простого текстового чата, основанного на технологии Peer-to-Peer или P2P. В отличии от старичка Mel.Chat&#8217;а, который основан на постоянной долбежке сервера AJAX-запросами, в этом чате все очень похоже на технологию клиент/сервер. Создаются необходимые соединения, которые просто остаются открыты столько сколько нужно и просто ожидают данные, которые отправляют (публикуют) другие клиенты. Но если с технологией клиент/сервер все более или менее понятно (все клиенты соединяются с одним определенным сервером, и все коммуникации осуществляются путем отправки сообщений на сервер, который в свою очередь отправляет сообщения всем подключенным к нему клиентам), то с P2P у нас так не получится, потому что тут у нас нет какого-то определенного сервера, а каждый отдельный клиент должен быть подписан на всех других участвующих в чате клиентов.</p>
<p>Схема ясна, переходим к практике.</p>
<h3>Сервис регистрации Peer ID</h3>
<p>Во-первых необходимо организовать сервис обмена Peer ID (далее фингерпринт) между клиентами. Это нужно для того, чтобы каждый новый подключившийся клиент мог самостоятельно найти хотябы одного активного в данный момент клиента и установить с ним соединение. Ниже представлен простейший код такого сервиса на PHP &#038; MySQL:</p>
<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br />36<br /></div></td><td><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">&lt;?php</span><br />
<br />
<span style="color: #b1b100;">require</span> <span style="color: #0000ff;">'lib/db.php'</span><span style="color: #339933;">;</span><br />
<br />
Db<span style="color: #339933;">::</span><span style="color: #004000;">connect</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'localhost'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'user'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'password'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'database'</span><span style="color: #009900;">&#41;</span> or <span style="color: #990000;">die</span><span style="color: #009900;">&#40;</span>Db<span style="color: #339933;">::</span><span style="color: #004000;">error</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #990000;">define</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'DB_TABLE'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'p2pchat'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #000088;">$time</span> <span style="color: #339933;">=</span> <span style="color: #990000;">time</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #000088;">$cooldown</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">900</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// 15 min</span><br />
<span style="color: #000088;">$limit</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">5</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #666666; font-style: italic;">// удаляем все истекшие записи</span><br />
Db<span style="color: #339933;">::</span><span style="color: #004000;">delete</span><span style="color: #009900;">&#40;</span>DB_TABLE<span style="color: #339933;">,</span> <span style="color: #0000ff;">'timestamp &lt; '</span><span style="color: #339933;">.</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$time</span> <span style="color: #339933;">-</span> <span style="color: #000088;">$cooldown</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">isset</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$_GET</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'insert'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&amp;&amp;</span> <span style="color: #339933;">!</span> <span style="color: #990000;">empty</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$_GET</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'insert'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// выбираем последние обновленные записи для попытки соединения с ними</span><br />
&nbsp; &nbsp; <span style="color: #000088;">$fingerprints</span> <span style="color: #339933;">=</span> Db<span style="color: #339933;">::</span><span style="color: #004000;">select</span><span style="color: #009900;">&#40;</span>DB_TABLE<span style="color: #339933;">,</span> <span style="color: #0000ff;">'fingerprint'</span><span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">NULL</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'timestamp DESC'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$limit</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// записываем в базу свой фингерпринт</span><br />
&nbsp; &nbsp; Db<span style="color: #339933;">::</span><span style="color: #004000;">insert</span><span style="color: #009900;">&#40;</span>DB_TABLE<span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'fingerprint'</span> <span style="color: #339933;">=&gt;</span> Db<span style="color: #339933;">::</span><span style="color: #004000;">escape</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$_GET</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'insert'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'timestamp'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$time</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// отправляем в ответ выбранные записи</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">sizeof</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$fingerprints</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&gt;</span> <span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$response</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$fingerprints</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$fp</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$response</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$fp</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'fingerprint'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">echo</span> <span style="color: #990000;">implode</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">','</span><span style="color: #339933;">,</span> <span style="color: #000088;">$response</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span> <span style="color: #b1b100;">else</span> <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">isset</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$_GET</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'update'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&amp;&amp;</span> <span style="color: #339933;">!</span> <span style="color: #990000;">empty</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$_GET</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'update'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// обновляем свой фингерпринт</span><br />
&nbsp; &nbsp; Db<span style="color: #339933;">::</span><span style="color: #004000;">update</span><span style="color: #009900;">&#40;</span>DB_TABLE<span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'timestamp'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$time</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'fingerprint = &quot;'</span><span style="color: #339933;">.</span>Db<span style="color: #339933;">::</span><span style="color: #004000;">escape</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$_GET</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'update'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'&quot;'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span></div></td></tr></tbody></table></div>
<p>Давайте я немного расскажу о принципе работы этого сервиса (или трекера). После того как ваш flash-клиент установил соединение с сервисом <a href="http://labs.adobe.com/technologies/stratus/">Stratus</a> он отправляет GET-запрос с вашим Peer ID в качестве параметра сервису регистрации фингерпринтов. Ваш фингерпринт сохраняется в базе с текущим временем. Также сервис выбирает из базы несколько последних добавленных/обновленных фингерпринтов и отправляет их в ответ вашему клиенту. Клиент пытается установить соединение с каждым из полученных фингерпринтов:</p>
<div class="codecolorer-container actionscript default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br /></div></td><td><div class="actionscript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">var</span> loader:URLLoader = <span style="color: #000000; font-weight: bold;">new</span> URLLoader<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;<br />
<br />
loader.<span style="color: #006600;">addEventListener</span><span style="color: #66cc66;">&#40;</span>Event.<span style="color: #006600;">COMPLETE</span>, <span style="color: #000000; font-weight: bold;">function</span><span style="color: #66cc66;">&#40;</span><span style="color: #0066CC;">e</span>:Event<span style="color: #66cc66;">&#41;</span>:<span style="color: #0066CC;">void</span> <span style="color: #66cc66;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #0066CC;">log</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'Insert fingerprint complete'</span><span style="color: #66cc66;">&#41;</span>;<br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">var</span> <span style="color: #0066CC;">fps</span>:<span style="color: #0066CC;">Array</span> = <span style="color: #0066CC;">e</span>.<span style="color: #0066CC;">target</span>.<span style="color: #0066CC;">data</span>.<span style="color: #0066CC;">split</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">','</span><span style="color: #66cc66;">&#41;</span>;<br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #808080; font-style: italic;">// перебираем все полученные фингерпринты,</span><br />
&nbsp; &nbsp; <span style="color: #808080; font-style: italic;">// и пытаемся с ними соединиться</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">for</span> <span style="color: #66cc66;">&#40;</span><span style="color: #000000; font-weight: bold;">var</span> i:<span style="color: #0066CC;">int</span> = <span style="color: #cc66cc;">0</span>; i <span style="color: #66cc66;">&lt;</span> <span style="color: #0066CC;">fps</span>.<span style="color: #0066CC;">length</span>; i++<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #66cc66;">&#40;</span><span style="color: #0066CC;">fps</span><span style="color: #66cc66;">&#91;</span>i<span style="color: #66cc66;">&#93;</span>.<span style="color: #0066CC;">length</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; initRecvStream<span style="color: #66cc66;">&#40;</span><span style="color: #0066CC;">fps</span><span style="color: #66cc66;">&#91;</span>i<span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #66cc66;">&#125;</span><br />
<span style="color: #66cc66;">&#125;</span><span style="color: #66cc66;">&#41;</span>;<br />
<br />
<span style="color: #0066CC;">try</span> <span style="color: #66cc66;">&#123;</span><br />
&nbsp; &nbsp; loader.<span style="color: #0066CC;">load</span><span style="color: #66cc66;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> URLRequest<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'http://url/to/p2pchatreg.php?insert='</span>+myPeerID<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>;<br />
<span style="color: #66cc66;">&#125;</span> <span style="color: #0066CC;">catch</span> <span style="color: #66cc66;">&#40;</span><span style="color: #0066CC;">error</span>:<span style="color: #0066CC;">Error</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #0066CC;">log</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'Unable to insert my peer id'</span><span style="color: #66cc66;">&#41;</span>;<br />
<span style="color: #66cc66;">&#125;</span></div></td></tr></tbody></table></div>
<p>И тут начинается самое интересное&#8230;</p>
<h3>Оповещение о новом участнике</h3>
<p>Так как запрос регистрации возвращает ограниченное количество последних обновленных фингерпринтов, наш клиент не сможет подключиться ко всем участвующим в чате клиентам, но этого и не потребуется, потому что клиенты сами &#8220;рассказывают&#8221; друг другу о подключении новых участников к чату, а также оповещают подключающихся к ним клиентах о своих именах:</p>
<div class="codecolorer-container actionscript default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br /></div></td><td><div class="actionscript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">client.<span style="color: #006600;">onPeerConnect</span> = <span style="color: #000000; font-weight: bold;">function</span><span style="color: #66cc66;">&#40;</span>subscriber:<span style="color: #0066CC;">NetStream</span><span style="color: #66cc66;">&#41;</span>:<span style="color: #0066CC;">Boolean</span> <span style="color: #66cc66;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #808080; font-style: italic;">// когда ко мне присоединяется подписчик, проверяем,</span><br />
&nbsp; &nbsp; <span style="color: #808080; font-style: italic;">// если это новый подписчик, то оповещаем всех о нем,</span><br />
&nbsp; &nbsp; <span style="color: #808080; font-style: italic;">// а также подписываемся на его поток</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">!</span> hasSubscriptionTo<span style="color: #66cc66;">&#40;</span>subscriber.<span style="color: #006600;">farID</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; sendStream.<span style="color: #0066CC;">send</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'onBroadcastNewSubscriber'</span>, subscriber.<span style="color: #006600;">farID</span><span style="color: #66cc66;">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; initRecvStream<span style="color: #66cc66;">&#40;</span>subscriber.<span style="color: #006600;">farID</span><span style="color: #66cc66;">&#41;</span>;<br />
&nbsp; &nbsp; <span style="color: #66cc66;">&#125;</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #808080; font-style: italic;">// ... и конечно же оповещаем его о своем имени</span><br />
&nbsp; &nbsp; subscriber.<span style="color: #0066CC;">send</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'onPeerNameUpdate'</span>, myPeerID, myName<span style="color: #66cc66;">&#41;</span>;<br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #b1b100;">return</span> <span style="color: #000000; font-weight: bold;">true</span>;<br />
<span style="color: #66cc66;">&#125;</span>;</div></td></tr></tbody></table></div>
<p>Итак, подключившись хотя бы к одному активному участнику чата или пиру (от англ. peer), тот немедленно проверяет свой список подключенных к нему пиров, и если вашего клиента с его уникальным peer id там еще нет, то он оповещает всех о новом подключенном к конференции клиенте, и все уже связанные друг с другом пиры сами устанавливают соединение с вами. Таким образом образуется самоформирующаяся группа участников конференции (во Flash Player 10.1 всю эту механику берет на себя новый класс NetGroup + GroupSpecifier).</p>
<h3>Актуальность фингерпринтов</h3>
<p>Актуальность активных в данный момент фингерпринтов &#8211; это ключевой момент всего приложения. Чтобы поддерживать актуальность своего фингерпринта каждый активный клиент через определенный промежуток времени отправляет GET-запрос на сервис регистрации фингерпринтов с просьбой обновить время активности своего фингерпринта:</p>
<div class="codecolorer-container actionscript default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br /></div></td><td><div class="actionscript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #808080; font-style: italic;">// запускаем таймер который будет тикать каждые 5 минут (300 секунд)</span><br />
<span style="color: #000000; font-weight: bold;">var</span> timer:Timer = <span style="color: #000000; font-weight: bold;">new</span> Timer<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">300</span> <span style="color: #66cc66;">*</span> <span style="color: #cc66cc;">1000</span><span style="color: #66cc66;">&#41;</span>;<br />
<br />
timer.<span style="color: #006600;">addEventListener</span><span style="color: #66cc66;">&#40;</span>TimerEvent.<span style="color: #006600;">TIMER</span>, <span style="color: #000000; font-weight: bold;">function</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>:<span style="color: #0066CC;">void</span> <span style="color: #66cc66;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">var</span> loader:URLLoader = <span style="color: #000000; font-weight: bold;">new</span> URLLoader<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;<br />
<br />
&nbsp; &nbsp; loader.<span style="color: #006600;">addEventListener</span><span style="color: #66cc66;">&#40;</span>Event.<span style="color: #006600;">COMPLETE</span>, <span style="color: #000000; font-weight: bold;">function</span><span style="color: #66cc66;">&#40;</span><span style="color: #0066CC;">e</span>:Event<span style="color: #66cc66;">&#41;</span>:<span style="color: #0066CC;">void</span> <span style="color: #66cc66;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0066CC;">log</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'Update fingerprint complete'</span><span style="color: #66cc66;">&#41;</span>;<br />
&nbsp; &nbsp; <span style="color: #66cc66;">&#125;</span><span style="color: #66cc66;">&#41;</span>;<br />
<br />
&nbsp; &nbsp; <span style="color: #0066CC;">try</span> <span style="color: #66cc66;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; loader.<span style="color: #0066CC;">load</span><span style="color: #66cc66;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> URLRequest<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'http://url/to/p2pchatreg.php?update='</span>+myPeerID<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>;<br />
&nbsp; &nbsp; <span style="color: #66cc66;">&#125;</span> <span style="color: #0066CC;">catch</span> <span style="color: #66cc66;">&#40;</span><span style="color: #0066CC;">error</span>:<span style="color: #0066CC;">Error</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0066CC;">log</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'Unable to update my peer id'</span><span style="color: #66cc66;">&#41;</span>;<br />
&nbsp; &nbsp; <span style="color: #66cc66;">&#125;</span><br />
<span style="color: #66cc66;">&#125;</span><span style="color: #66cc66;">&#41;</span>;<br />
<br />
timer.<span style="color: #0066CC;">start</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;</div></td></tr></tbody></table></div>
<p>Таким образом новые участники конференции всегда получают пачку самых последних активных пиров на данный момент. И подключившись хотя бы к одному активному пиру, тот в свою очередь, оповещает всех о новом участнике.</p>
<h3>Заключение</h3>
<p>В итоге, у нас получается достаточно простой чат, который не использует сервер для передачи сообщений, и поддерживает большое количество клиентов онлайн. Мгновенно отправляет и получает сообщения. К такому чату можно добавить аудио/видео звонки и передачу файлов (аля Skype). Основными требованиями для работы такого чата являются наличие установленного Flash Player 10.0+ и разрешенный UDP-траффик.</p>
<p>В следующей статье я расскажу об использовании более удобных средств для организации групп при помощи классов NetGroup и GroupSpecifier из FlashPlayer 10.1.</p>
<p>Если вы хотите быть в курсе моих новых публикаций о flash и peer-to-peer, то не стесняйтесь и подписывайтесь на <a href="http://melnaron.net/feed" target="_blank">RSS-ленту моего блога</a> или <a href="http://twitter.com/Melnaron" target="_blank">следите за мной в Twitter</a>.</p>
<p><a href="http://melnaron.net/flash/p2pchat/" target="_blank"><strong>Живой пример P2PChat</strong></a> &#8211; Чтобы опробовать чат откройте его в 2х или более окнах браузера, расположите их рядом друг с другом и попробуйте что-нибудь написать.</p>
<p><a href="http://melnaron.net/files/P2PChat.zip"><strong>Скачать исходные коды P2PChat</strong></a> &#8211; Для Flash Builder 4 + Flex SDK 4. Для работы со Стратусом вам необходимо получить &#8220;stratus developer key&#8221; зайдя на страницу <a href="http://labs.adobe.com/technologies/stratus/">Stratus</a> и перейдя по ссылке &#8220;Signup for a Stratus beta developer key&#8221;.</p>
]]></content:encoded>
			<wfw:commentRss>http://melnaron.net/development/peer-to-peer-chat-in-flash/feed</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>MEL.Chat: Теперь с MySQL!</title>
		<link>http://melnaron.net/projects/melchat-%d1%82%d0%b5%d0%bf%d0%b5%d1%80%d1%8c-%d1%81-mysql</link>
		<comments>http://melnaron.net/projects/melchat-%d1%82%d0%b5%d0%bf%d0%b5%d1%80%d1%8c-%d1%81-mysql#comments</comments>
		<pubDate>Sun, 22 Feb 2009 17:55:33 +0000</pubDate>
		<dc:creator>Melnaron</dc:creator>
				<category><![CDATA[Projects]]></category>
		<category><![CDATA[mel.chat]]></category>
		<category><![CDATA[MySQL]]></category>

		<guid isPermaLink="false">http://melnaron.net/?p=166</guid>
		<description><![CDATA[Итак, как я и обещал, выкладываю новую бета-версию чата, теперь с поддержкой СУБД MySQL. Скачать MEL.Chat 2.0b3 А теперь немного об установке и настройке серверной части. Для начала откройте файл server/cfg.php и отредактируйте данные для подключения к MySQL-серверу. Затем запустите скрипт server/setup.php для создания необходимых таблиц в БД. Вот и все, что нужно сделать. Далее [...]]]></description>
			<content:encoded><![CDATA[<p>Итак, как я и обещал, выкладываю новую бета-версию чата, теперь с поддержкой СУБД MySQL.</p>
<p><a href="http://melchat.googlecode.com/files/mel.chat_2.0b3.zip">Скачать MEL.Chat 2.0b3</a></p>
<p>А теперь немного об установке и настройке серверной части. Для начала откройте файл server/cfg.php и отредактируйте данные для подключения к MySQL-серверу. Затем запустите скрипт server/setup.php для создания необходимых таблиц в БД. Вот и все, что нужно сделать. Далее заходим в чат под любым никнеймом и регистрируемся как администратор с помощью команды /reg [ваш_пароль].</p>
]]></content:encoded>
			<wfw:commentRss>http://melnaron.net/projects/melchat-%d1%82%d0%b5%d0%bf%d0%b5%d1%80%d1%8c-%d1%81-mysql/feed</wfw:commentRss>
		<slash:comments>160</slash:comments>
		</item>
	</channel>
</rss>

