tag:blogger.com,1999:blog-23683027776427624402024-03-08T23:15:27.111+03:00Записки программистаfalkohttp://www.blogger.com/profile/11555150920503978486noreply@blogger.comBlogger5125tag:blogger.com,1999:blog-2368302777642762440.post-87102290266925108262013-10-18T18:45:00.002+04:002013-10-18T18:56:21.784+04:003g модем и уровень сигнала в linux<div dir="ltr" style="text-align: left;" trbidi="on">
Простой способ померить уровень сигнала в консоли linux.<br />
Открываем две консольки, в одной выполняем команду:<br />
<br />
<blockquote class="tr_bq">
cat /dev/ttyUSB1</blockquote>
В другой:<br />
<blockquote class="tr_bq">
echo -e "AT+CSQ\r\n" > /dev/ttyUSB1</blockquote>
<br />
<a name='more'></a>И быстренько смотрим первую консольку, ищем там строчки:<br />
<blockquote class="tr_bq">
+CSQ:<span style="color: #38761d;"> <span style="color: black;"><b>23</b></span></span>,99<br />
<br />
OK</blockquote>
Пробуйте ttyUSB0, ttyUSB2... если не удается на первом. <br />
Расшифровываем по табличке, нас интересует первая цифра до запятой:<br />
<br />
<table border="0" cellpadding="0" cellspacing="0" style="width: 200px;"><tbody>
<tr><td height="20" width="64"><b>Value</b></td>
<td width="85"><b>RSSI dBm</b></td>
<td width="117"><b>Condition</b></td>
</tr>
<tr>
<td height="20">2</td>
<td>-109</td>
<td>Marginal</td>
</tr>
<tr>
<td height="20">3</td>
<td>-107</td>
<td>Marginal</td>
</tr>
<tr>
<td height="20">4</td>
<td>-105</td>
<td>Marginal</td>
</tr>
<tr>
<td height="20">5</td>
<td>-103</td>
<td>Marginal</td>
</tr>
<tr>
<td height="20">6</td>
<td>-101</td>
<td>Marginal</td>
</tr>
<tr>
<td height="20">7</td>
<td>-99</td>
<td>Marginal</td>
</tr>
<tr>
<td height="20">8</td>
<td>-97</td>
<td>Marginal</td>
</tr>
<tr>
<td height="20">9</td>
<td>-95</td>
<td>Marginal</td>
</tr>
<tr>
<td height="20">10</td>
<td>-93</td>
<td>OK</td>
</tr>
<tr>
<td height="20">11</td>
<td>-91</td>
<td>OK</td>
</tr>
<tr>
<td height="20">12</td>
<td>-89</td>
<td>OK</td>
</tr>
<tr>
<td height="20">13</td>
<td>-87</td>
<td>OK</td>
</tr>
<tr>
<td height="20">14</td>
<td>-85</td>
<td>OK</td>
</tr>
<tr>
<td height="20">15</td>
<td>-83</td>
<td>Good</td>
</tr>
<tr>
<td height="20">16</td>
<td>-81</td>
<td>Good</td>
</tr>
<tr>
<td height="20">17</td>
<td>-79</td>
<td>Good</td>
</tr>
<tr>
<td height="20">18</td>
<td>-77</td>
<td>Good</td>
</tr>
<tr>
<td height="20">19</td>
<td>-75</td>
<td>Good</td>
</tr>
<tr>
<td height="20">20</td>
<td>-73</td>
<td>Excellent</td>
</tr>
<tr>
<td height="20">21</td>
<td>-71</td>
<td>Excellent</td>
</tr>
<tr>
<td height="20">22</td>
<td>-69</td>
<td>Excellent</td>
</tr>
<tr>
<td height="20"><b>23</b></td>
<td><b>-67</b></td>
<td><b>Excellent</b></td>
</tr>
<tr>
<td height="20">24</td>
<td>-65</td>
<td>Excellent</td>
</tr>
<tr>
<td height="20">25</td>
<td>-63</td>
<td>Excellent</td>
</tr>
<tr>
<td height="20">26</td>
<td>-61</td>
<td>Excellent</td>
</tr>
<tr>
<td height="20">27</td>
<td>-59</td>
<td>Excellent</td>
</tr>
<tr>
<td height="20">28</td>
<td>-57</td>
<td>Excellent</td>
</tr>
<tr>
<td height="20">29</td>
<td>-55</td>
<td>Excellent</td>
</tr>
<tr>
<td height="20">30</td>
<td>-53</td>
<td>Excellent</td></tr>
</tbody></table>
<br />
Подробнее о команде <a href="http://m2msupport.net/m2msupport/atcsq-signal-quality/" target="_blank">читаем тут</a>. <br />
<br />
<br /></div>
falkohttp://www.blogger.com/profile/11555150920503978486noreply@blogger.com0tag:blogger.com,1999:blog-2368302777642762440.post-28341514673212888682013-07-04T10:59:00.000+04:002013-07-04T10:59:12.574+04:00Как узнать модель материнской платы в linuxБыстрый и простой способ: <br />
<blockquote class="tr_bq">
<pre><code>sudo dmidecode -t 2</code></pre>
</blockquote>
<a href="http://askubuntu.com/questions/179958/how-do-i-find-out-my-motherboard-model/179959" target="_blank">Другие способы включая варианты с гуем</a> falkohttp://www.blogger.com/profile/11555150920503978486noreply@blogger.com0tag:blogger.com,1999:blog-2368302777642762440.post-61575218734443134292013-07-03T21:44:00.001+04:002016-04-16T20:53:54.831+03:00Лечим потерю сессии Firefox в Mac OS Lion при закрытии окна через красную кнопочку (x) Так уж сложилось, что я ярый поклонник огнелиса. Начав пользоваться им в Mac OS Lion заметил, что закрывая окно, приложение остается запущенным и повторный запуск из док панели открывает новое окно, но уже без последних открытых вкладок. Пару таких финтов с потерей непосильным трудом найденных страниц, но еще не разложенных по закладкам и я полез гуглить. И вот, что выяснил.<br />
Маководы могут посмеяться, но оказалось почти все если не все приложения в маке остаются открытыми пока их явно не закроешь через Command+Q. Но, огнелис запоминает сессию только при закрытии приложения и, получается, закрывая окно и оставляя приложение открытым мы собственноручно отказываемся от текущей сессии, новое окно уже без вкладок.<br />
Оставалась очень не приятная перспектива, следить за собой и выходить из огнелиса явно через док панель, хоткеем или через меню... С привычками сложно бороться и я начал поиски.<br />
<div id="icon">
Решения и оно нашлось! Сразу скажу, если кто знает иное решение или найдет его позже, милости просим, расскажите в коментах. Так вот, есть такая программка RedQuits, скачать ее можно <span style="color: black;"><a href="http://www.carsten-mielke.com/redquits.html" target="_blank">здесь</a>. Программка может сама стартовать после логина и ее можно настроить так, чтобы приложение закрывалось только если закрываем последнее окно! Тадам! То, что доктор прописал! </span></div>
<div id="icon">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<span style="color: black;"><a href="http://www.carsten-mielke.com/Media/redquits_preferences_quit.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="137" src="http://www.carsten-mielke.com/Media/redquits_preferences_quit.jpg" width="320" /></a></span></div>
<br />
<div id="icon">
<br /></div>
<div id="icon">
<span style="color: #990000;"><span style="color: black;">Дальше думаю сами разберетесь, удачи!</span></span></div>
falkohttp://www.blogger.com/profile/11555150920503978486noreply@blogger.com1tag:blogger.com,1999:blog-2368302777642762440.post-74263917420127032912012-02-16T12:24:00.005+04:002013-01-14T16:56:55.624+04:00Android root из Linux<div dir="ltr" style="text-align: left;" trbidi="on">
Это руководство для тех, кто хочет получить права root на своем Android телефоне.<br />
<a name='more'></a><br />
<br />
[Предварительное рутование может и не потребоваться при переходе непосредственно на нестандартные прошивки, такие как: CM7 или MIUI через Odin/Heimdall, в любом случае вам потребуется ADB (пункты 1-4)]<br />
<br />
<br />
<div class="almost_half_cell" id="gt-res-content">
<div dir="ltr" style="zoom: 1;">
<b><span class="" id="result_box" lang="ru"><span class="">Прежде чем начнем сделаем р</span></span></b><b><span class="" id="result_box" lang="ru"><span class="hps">езервную копию данных</span><span class="">, </span> <span class="hps">на всякий случай.</span></span></b></div>
</div>
<br />
<b>1. Установка ADB</b><br />
<ul style="text-align: left;">
<li> Скачайте <a href="http://developer.android.com/sdk/index.html" target="_blank">Android-SDK</a> для linux. <i>[Это пакет инструментов для разработчиков под Android]</i> </li>
<li>Распакуйте директорию /tools на рабочий стол. <i>[Возможно для этого понадобится установить архиватор 7zip. Он есть в репозиториях Ubuntu.]</i> </li>
<li>Создайте директорию "bin" и поместите туда программу ADB: </li>
</ul>
<blockquote class="tr_bq" style="font-family: "Courier New",Courier,monospace;">
<blockquote class="tr_bq">
mkdir -p ~/bin <br />
mv ~/Desktop/tools/adb ~/bin/</blockquote>
</blockquote>
<br />
<b>2. Сбор необходимой информации</b><br />
<ul style="text-align: left;">
<li> На вашем телефоне перейдите <i><span class="st">Насторйки=>Приложения=>Разработка<i></i></span> (Settings=>Applications=>Development)</i> и включите опцию <span class="st"><i>Отладка по USB(</i></span><i>USB debugging)</i></li>
<li>Подключите ваш телефон к компьютеру. <i>[*В режиме телефона, не в режиме USB накопителя]</i> </li>
<li>В терминале на компьютере выполните "<b style="font-family: Verdana,sans-serif;">lsusb</b>" без кавычек</li>
<li>Одна из строк в результате должна быть похожа на что-то вроде (в зависимости от производителя вашего телефона):<blockquote class="tr_bq" style="font-family: "Courier New",Courier,monospace;">
<span style="font-size: small;">Bus 001 Device 002: ID 04e8:681c Samsung Electronics Co., Ltd</span></blockquote>
</li>
</ul>
<ul style="text-align: left;">
<li> Запишите или запомните первые 4 символа после ID. Это идентификатор производителя (Vendor ID, в нашем примере 04e8). Номера Bus и Device будут разными всякий раз при переподключении телефона к компьютеру или после его перезагрузки.</li>
<li>В терминале выполните "<span style="font-size: small;"><b style="font-family: Verdana,sans-serif;">id</b></span>" без кавычек, эта команда покажет имя и группу пользователя под которым вы вошли в систему (если вы не уверены, что знаете их точно)</li>
</ul>
<br />
<b>3. Установка првила Udev для работы ADB</b><br />
<ul style="text-align: left;">
<li> Откройти любимый текстовый редатктор с правами root. Например, в терминале Kubuntu наберите "<span style="font-size: small;"><b style="font-family: Verdana,sans-serif;">kdesudo kate</b></span>".</li>
<li>Вставьте следующую строку без переносов в редактор и измените как указано ниже:<blockquote class="tr_bq">
<span style="font-family: "Courier New",Courier,monospace; font-size: small;">SUBSYSTEM=="usb", SYSFS{idVendor}=="<идентификатор производителя Vendor ID>", OWNER="<имя пользователя>" GROUP="<имя группы>"</span></blockquote>
Для нашего примера "<span style="font-family: inherit; font-size: small;"><</span><span style="font-family: "Courier New",Courier,monospace; font-size: small;">идентификатор производителя Vendor ID</span><span style="font-family: inherit; font-size: small;">></span>" заменяем "04e8". Не трогаете кавычки но заменяете < > и все, что в нутри. </li>
</ul>
<br />
<ul style="text-align: left;">
<li>Сохраните файл по этому пути /etc/udev/rules.d/51-android.rules</li>
<li>И ещё по этому пути /lib/udev/rules.d/51-android.rules</li>
</ul>
<i>[Примечание: Вообще вам нужен первый из них, но он может отличаться в разных системах]</i><br />
<ul style="text-align: left;">
<li>В терминале, наберите <span style="font-size: small;"><b><span style="font-family: Verdana,sans-serif;">ls /etc/udev/rules.d/51-android.rules</span></b></span> дабы убедиться, что файл на месте, аналогично для второго пути.</li>
<li>Перезапустите udev или перезагрузите компьютер чтобы изменения вступили в силу</li>
</ul>
<i>[Примечание: в некоторых руководствах при настройке првил udev рекомендуется устанавливать права доступа 0666 которые открывают доступ к файлу всем. Здесь мы назначаем доступ одному пользователю, которому это нужно, так будет безопаснее. Приоритет правила установили 51, это не принципиально, можно назначить и другой.] </i><br />
<br />
<b>4. </b><b>Проверяем что получилось</b><br />
<ul style="text-align: left;">
<li>В терминале наберите "<span style="font-size: small;"><b><span style="font-family: Verdana,sans-serif;">lsusb</span></b></span>", как делали это ранее</li>
<li>Одна из строк должна быть похожа на:<span style="font-size: x-small;"> </span><blockquote class="tr_bq">
<span style="font-family: "Courier New",Courier,monospace; font-size: small;">Bus 001 Device 002: ID 04e8:681c Samsung Electronics Co., Ltd</span><span style="font-family: "Courier New",Courier,monospace;"> </span></blockquote>
</li>
</ul>
<ul style="text-align: left;">
<li>В данный момент нас интересуют номера после Bus и Device, которые, возможно, изменились если вы перезагрузили компьютер.</li>
<li>В терминале выполните "<span style="font-size: small;"><b><span style="font-family: Verdana,sans-serif;">ls -l /dev/bus/usb/001/002</span></b></span>" ВНИМАНИЕ 001/002 это Bus/Device из примера выше, замените Bus/Device на цифры из вашего вывода команды "<span style="font-size: small;"><b><span style="font-family: Verdana,sans-serif;">lsusb</span></b></span>".</li>
<li>Если в результате команды имя пользователя и группа отличаются от "root root" можно продолжать дальше. Если это не так, перечитайте и повторите шаги 2 и 3.</li>
<li>*Убедитесь что ваш телефон все еще в режиме <span class="st"><i>Отладка по USB</i></span>. Должен быть красный треугольник с восклицательным знаком в строке состояния вашего телефона (зависит от темы и версии Android).</li>
<li>В терминале наберите "<span style="font-size: small;"><b><span style="font-family: Verdana,sans-serif;">sudo adb devices</span></b></span>" <i>[*sudo понадобится только при первом запуске adb.]</i></li>
</ul>
Вы должны увидеть свой телефон в списке.<br />
<br />
<b>5. Загрузка</b><b> <a href="http://theandroidsite.com/wp-content/uploads/2011/01/FascinateRoot_v02.zip" target="_blank">Samsung Fascinate Root Package</a><br />
</b>Эти файлы необходимы, хотя драйвера не нужны для Linux.<b><br />
<br />
6. Распаковка 4-х файлов в </b><b>~/bin<br />
</b>Эту директорию мы создали в шаге 1, там уже должен быть файл adb. Вы можете распаковать куда-нибудь загруженный архив и поместить необходимые файлы в ~/bin (это su, rage.bin, busybox, Superuser.apk).<b><br />
<br />
7. Переход в ~/bin<u> </u></b><br />
В терминале наберите "<span style="font-family: Verdana,sans-serif; font-size: small;"><b>cd ~/bin</b></span>", а затем "<span style="font-family: Verdana,sans-serif; font-size: small;"><b>ls</b></span>", должно быть 5 файлов.<br />
<br />
<b>8. Перенос файлов на телефон и запуск root: <br />
</b>Выполните каждую из следующих строк по отдельности в терминале, скопируйте и встаьте (жмите Enter после вставки каждой строки):<br />
<br />
<blockquote class="tr_bq" style="font-family: "Courier New",Courier,monospace;">
./adb push su /sdcard/su <br />
./adb push rage.bin /data/local/tmp/rage.bin <br />
./adb push busybox /sdcard/busybox <br />
./adb shell </blockquote>
<i>[Примечание: символ приглашения ввода строки должен измениться на <b>$</b>, это означает, что мы </i><i>удаленно</i><i> подключились к телефону] </i><br />
<blockquote class="tr_bq">
<div style="font-family: "Courier New",Courier,monospace;">
cd /data/local/tmp </div>
<div style="font-family: "Courier New",Courier,monospace;">
chmod 0755 rage.bin </div>
<div style="font-family: "Courier New",Courier,monospace;">
./rage.bin </div>
</blockquote>
<br />
<i>[Примечание: Эта комманда определит ограничение процесса, найдет номер процесса adb, а затем запускает процессы до исчерпания этого ограничения. Вы быстро вернетесь в строк сприглашением $, но <b>ЭТО НЕ ВСЕ. ЖДИТЕ</b> пока не выведется что-то похожее на "[+] Forked 3705 childs." и вы вернетесь в свою домашнюю директорию.]</i><br />
<br />
<b>9. Зафиксируем права root</b><br />
<ul style="text-align: left;">
<li>В терминале вернитесь в директорию ~/bin введите "<span style="font-family: Verdana,sans-serif; font-size: small;"><b>./adb shell</b></span>"<br />
<br />
На этот раз вы должны получить приглашение <b>#</b> вместо <b>$</b>. Это означает, что теперь вы удаленно зашли на телефон как root.</li>
<li>Скопируйте и вставьте каждую строку по отдельности (жмите Enter после каждой строки):</li>
</ul>
<blockquote class="tr_bq" style="font-family: "Courier New",Courier,monospace;">
mount -t rfs -o remount,rw /dev/block/stl9 /system <br />
cd /system/xbin <br />
cat /sdcard/su > su <br />
cat /sdcard/busybox > busybox <br />
chmod 4755 su <br />
chmod 4755 busybox <br />
exit <br />
./adb install Superuser.apk</blockquote>
<br />
<b>10. Убедимся что получили права root</b> <br />
<ul style="text-align: left;">
<li>Перезапускаем телефон</li>
<li>В терминале выполняем "<span style="font-size: small;"><b style="font-family: Verdana,sans-serif;">~/bin/adb shell</b></span>"<br />
Вы должны получить приглашение <b>$ </b> <br />
Выполните "<span style="font-size: small;"><b style="font-family: Verdana,sans-serif;">su</b></span>"<br />
На телефоне должно появиться всплывающее сообщение где запрашивается подтверждение использования прав суперпользователя. После того, как вы разрешите, приглашение должно измениться на <b>#</b></li>
</ul>
Это сообщение будет появляться всякий раз, когда вы устонавливаете и запускаете программу требующую привелегий пользователя root.<br />
Теперь запустите приложение SuperUser, оно должно показать список программ имеющих привелегии root пользователя.<br />
<br />
P.S. Исходный материал взят <a href="http://androidforums.com/fascinate-all-things-root/236081-how-root-using-ubuntu.html#post1995083" target="_blank">здесь</a></div>
falkohttp://www.blogger.com/profile/11555150920503978486noreply@blogger.com13tag:blogger.com,1999:blog-2368302777642762440.post-61535381405514975372008-06-06T00:08:00.000+04:002012-01-12T00:19:59.991+04:00Жизненный цикл запроса Zope3<div dir="ltr" style="text-align: left;" trbidi="on"><div style="text-align: justify;">При разработке приложений для Zope 3 разработчик часто взаимодействует с объектом запроса (<i>request</i>). Создавая представления, ему не надо задумываться о деталях того, откуда взялся запрос в <i>представлении</i> и что происходит с создаваемым в нем ответом (<i>response</i>). Все это хорошо, т.к. в большинстве случаев понимания внутреннего устройства не требуется. Но иногда нам может понадобиться создать собственный сервер или изменить поведение механизма публикации. В данном случае очень полезно знать общую архитектуру серверов и публикаторов Zope. Далее мы рассмотрим жизненный цикл запроса, а для примера возьмем запрос браузера (<i>HTTP Request</i>).</div><a name='more'></a><div style="text-align: justify;"><br />
</div><div style="padding-left: 60px; text-align: justify;">В данной статье подразумевается использование Zope 3.4. За основу взят материал <a href="http://wiki.zope.org/zope3/request.html" target="_blank" title="Chapter 40 The Life of a Request">главы 40</a> из книги <a href="http://wiki.zope.org/zope3/Zope3Book" target="_blank" title="http://wiki.zope.org/zope3/Zope3Book">The Zope 3 Developers Book - An Introduction for Python Programmers</a>. При использовании материалов данного документа как полностью, так и частично, ссылка на оригинал обязательна.</div><div style="text-align: justify;"><b>Что же такое запрос?</b></div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;">Технически, в конкретной ситуации мы обычно ссылаемся на объекты реализующие интерфейс <b>IRequest</b>. Эти объекты отвечают за внутренние устройство, специфичное протоколу и представляют семантику протокола для использования презентационными компонентами.</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;">В общем смысле все, что посылает клиент серверу после установления соединения и есть</div><div style="text-align: justify;">запрос. На более низком уровне клиентское приложение (браузер) посылает HTTP строку</div><div style="text-align: justify;">примерно такого вида:</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;"><b>GET /index.html HTTP/1.1</b></div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;">в общем, это и есть запрос.</div><br />
<br />
<br />
<b>Где начинается запрос?</b><br />
<div class="separator" style="clear: both; text-align: center;"><a href="http://1.bp.blogspot.com/-jyWmNfHA2nc/Tw3r9wTjBpI/AAAAAAAAAHs/KttF4wIMYHI/s1600/lor.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="219" src="http://1.bp.blogspot.com/-jyWmNfHA2nc/Tw3r9wTjBpI/AAAAAAAAAHs/KttF4wIMYHI/s320/lor.png" width="320" /></a></div><div style="text-align: justify;">Теперь мы понимаем, что же такое запрос, углубимся в детали и посмотрим, как обрабатываются соединения и рождается запрос.</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;">При запуске, сервер привязывается к сокету на локальном адресе машины и начинает прослушивание входящих соединений. При обнаружении входящего соединения, вызывается метод <b>accept()</b>, который возвращает объект соединения и адрес компьютера, с которым оно установлено. Все выше описанное является частью стандартной библиотеки сокетов Python и документировано в интерфейсе <b>zope.server.interfaces.ISocket </b>(файл:<i> .../zope/server/interfaces/__init__.py</i>).</div><div style="text-align: justify;"><br />
</div><div class="separator" style="clear: both; text-align: justify;"><a href="http://2.bp.blogspot.com/-KUjEdz_rYqo/Tw3sh9ECDEI/AAAAAAAAAH0/I0d9dvWGIQ4/s1600/cd.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="265" src="http://2.bp.blogspot.com/-KUjEdz_rYqo/Tw3sh9ECDEI/AAAAAAAAAH0/I0d9dvWGIQ4/s320/cd.png" width="320" /></a></div><div style="text-align: justify;"><a href="http://blog.falkolab.ru/wp-content/uploads/2008/05/cd.png" title="Диограмма классов"></a>Сервер, который по большей части является реализацией <b>IDispatcher</b>, имеет простой интерфейс для обработки событий вызовом соответствующих методов <b>handle_<event>()</b>. Полный список всех событий, обрабатываемых таким образом, приведен в интерфейсе <b>IDispatcherEventHandler</b> (<i>.../zope/server/interfaces/__init__.py</i>).</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;">Таким образом, когда поступает входящее соединение вызывается метод <b>handle_accept()</b>, который переопределен в классе <b>zope.server.serverbase.ServerBase</b>. Этот метод пытается получить соединение вызывая метод <b>accept()</b>. При успешном создании соединения, оно используется для создания канала <b>ServerChannel</b>, являющегося следующим уровнем абстракции. Большая часть остальной функциональности диспетчера предоставляется <b>async.dispatcher</b>, который полностью реализует интерфейс <b>IDispatcher</b>.</div><br />
<blockquote class="tr_bq"><pre lang="python"><span style="font-size: small;">def handle_accept(self):
"""See zope.server.interfaces.IDispatcherEventHandler"""
try:
v = self.accept()
if v is None:
return
conn, addr = v
except socket.error:
if self.adj.log_socket_errors:
self.log_info ('warning: server accept() threw an exception',
'warning')
return
for (level, optname, value) in self.adj.socket_options:
conn.setsockopt(level, optname, value)
self.channel_class(self, conn, addr, self.adj)</span></pre></blockquote><pre lang="python"> </pre><div class="separator" style="clear: both; text-align: center;"><a href="http://3.bp.blogspot.com/-UuTxDc0qfJI/Tw3tG33q9wI/AAAAAAAAAH8/DKJko0j1Nes/s1600/lor2.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="300" src="http://3.bp.blogspot.com/-UuTxDc0qfJI/Tw3tG33q9wI/AAAAAAAAAH8/DKJko0j1Nes/s320/lor2.png" width="320" /></a></div><div style="text-align: justify;">На этой стадии канал принимает управление на себя, ведь это всего лишь еще один диспетчер. Таким образом канал запускается для того, чтобы собрать поступающие данные (см. <b>received(data)</b> в <i>.../zope/server/serverchannelbase.py</i>) и немедленно передает их анализатору запросов, экземпляру класса, заданного в переменной <b>parser_class</b>. Естественно, этот класс будет разным в других реализациях сервера (например FTP). Как именно функционирует анализатор не так важно, нам надо знать только что он реализует <b>IStreamConsumer</b>, посредством которого он сообщает о завершении разбора запроса (атрибут <b>completed</b>). В канале может существовать только один запрос, таким образом если канал занят, поступающие запросы помещаются в очередь до тех пор, пока выполняемая задача не будет завершена.</div><blockquote class="tr_bq"><pre lang="python"><span style="font-size: small;">def received(self, data):
"""See async.dispatcher
Receives input asynchronously and send requests to
handle_request().
"""
preq = self.proto_request
while data:
if preq is None:
preq = self.parser_class(self.adj)
n = preq.received(data)
if preq.completed:
# The request is ready to use.
self.proto_request = None
if not preq.empty:
self.handle_request(preq)
preq = None
else:
self.proto_request = preq
if n >= len(data):
break
data = data[n:]
def handle_request(self, req):
"""Creates and queues a task for processing a request.
Subclasses may override this method to handle some requests
immediately in the main async thread.
"""
task = self.task_class(self, req)
self.queue_task(task)
def queue_task(self, task):
"""Queue a channel-related task to be executed in another thread."""
start = False
task_lock.acquire()
try:
if self.tasks is None:
self.tasks = []
self.tasks.append(task)
if not self.running_tasks:
self.running_tasks = True
start = True
finally:
task_lock.release()
if start:
self.set_sync()
self.server.addTask(self)</span></pre></blockquote><div style="text-align: justify;">Всякий раз, после освобождения канала (см. <b>handle_request(self, req)</b> ) запрос приводится к интерфейсу <b>ITask</b> и помещается в очередь (см. <b>queue_task(task)</b> ). Если в данный момент есть другие задачи канала в процессе обработки сервером, то задача помещается в очередь, иначе канал с накопленными задачами немедленно передается серверу на выполнение используя метод <b>IServer.addTask(task)</b> (да, канал тоже реализует <b>ITask</b>). В этом методе задача добавляется в диспетчер задач (см. <b>ITaskDispatcher</b>), который планирует ее выполнение в отдельном потоке. Но почему все это делается через задачи и диспетчер задач? Ранее весь код выполнялся в одном потоке. но для улучшения масштабирования и поддержки долго живущих запросов без блокирования всего сервера, механизму обработки запроса необходимо иметь возможность запуска нескольких параллельных потоков. Итак, реализация <b> ITaskDispatcher</b> отвечает за распределение запросов. Теоретически он даже может задействовать другие компьютеры для выполнения задач. Тем не менее по умолчанию используется <b>zope.server.taskthreads.ThreadedTaskDispatcher</b>. Используя его метод <b>setThreadCount(count)</b>, механизм запуска Zope может задавать максимальное количество одновременно работающих потоков.</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;">Как только задачи поступают на обработку, диспетчер вызывает метод <b> ITask.service()</b> который должен выполнить запрос. В частности, когда обрабатывается <b> HTTPTask</b>, вызывается метод <b>executeRequest(task)</b> сервера <b>HTTPServer</b>. Публикатор <b>zope.server.http.publisherhttpserver.PublisherHTTPServer</b>, это единственное, что непосредственно относится к Zope 3, он создает объект <b>IHTTPRequest</b> из задачи и публикует запрос через <b>zope.publisher.publish(request)</b>. Сервер имеет атрибут <b>request_factory</b> в котором содержится используемый для создания запросов класс.</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;">Так к чему же пришла система? Мы взяли входящее соединение, прочитали все входящие данные и провели их разбор, запланировали выполнение и на основе этого создали запрос, который был опубликован публикатором Zope 3. Все кроме последнего шага не содержит никакого специфичного для Zope 3 кода, а это значит, что все это может быть заменено на другой Web-сервер, например Twisted.</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;">На этом заканчивается процесс создания запроса. В следующей статье мы рассмотрим его публикацию.</div></div>falkohttp://www.blogger.com/profile/11555150920503978486noreply@blogger.com1