Entries by category: it
Category was added automatically. Read all entries about "it".
Убивает наповал то, что вопрос, который я решил бы с разработчиками минут за пятнадцать, требует от меня:
1. Подготовки презентации а-ля "Азбука в картинках".
2. Обсуждения всех этих комиксов с линейными руководителями для уточнения цифр и позиций.
3. Рассылку комиксов ТОП-ам.
4. Ответов по e-mail на вопросы вида: "Какими источниками вы пользовались при расчёте количества архитекторов, необходимых нашей компании".
5. Повторения п.4. в устной форме на специально созываемом собрании.
6. Ответа на протокол специально созываемого собрания.

How time feels when participating in a meeting with non-technical people
( Ну и любимые кадры заодно прикопал...Collapse )
1. Подготовки презентации а-ля "Азбука в картинках".
2. Обсуждения всех этих комиксов с линейными руководителями для уточнения цифр и позиций.
3. Рассылку комиксов ТОП-ам.
4. Ответов по e-mail на вопросы вида: "Какими источниками вы пользовались при расчёте количества архитекторов, необходимых нашей компании".
5. Повторения п.4. в устной форме на специально созываемом собрании.
6. Ответа на протокол специально созываемого собрания.

How time feels when participating in a meeting with non-technical people
( Ну и любимые кадры заодно прикопал...Collapse )
Оригинал взят у
mpd в Вакансия ведущего Perl-разработчика в wada.vn (Ашманов и партнеры)
( Read more...Collapse )
Уважаемые профессионалы!
Компания "Ашманов и партнеры", приглашает к сотрудничеству Ведущего Perl-разработчика.( Read more...Collapse )
Недавно Роман Овчинников научил меня оченно полезной магии -- bash -x. Это сочетание даёт возможность проследить выполнение скрипта шаг за шагом, строка за строкой, что очень мне помогло в понимании творчества наших немецких коллег. Чтобы не растекаться мыслью, вот ссылка.
Продолжаю развлекаться с RoR.
Поскольку использовать sqlite неинтересно,
решил заправить какую-нибудь другую СУБД,
например MySQL.
После непродолжительного, но яркого секса сделал следующие выводы:
1. Устанавливать всякие gem лучше через rvm (Ruby Version Manager).
В этом случае вероятность ошибок, выдаваемых gem, падает в разы.
С gem для установки mysql я вообще совладать не смог.
Он ругался и на отсутствие native libraries, потом сказал, мол не могу получить доступ к памяти,
пару раз ложился с суровым некрологом "Segmentation fault". Так что rvm, однозначно.
Да, поставить rvm с помощью gem мне тоже не удалось, пришлось тащить из git-репозитория.
Соответственно, для rvm, понадобится ещё и git.
2. При генерации базы данных возможны неочевидные ошибки.
Так мне выдалось сообщение, цитирую:
$ sudo rake --trace db:create
...
** Invoke db:create (first_time)
** Invoke db:load_config (first_time)
** Invoke rails_env (first_time)
** Execute rails_env
** Execute db:load_config
** Execute db:create
rake aborted!
can't convert Fixnum into String
...
Ошибка обнаружилась в config/database.yml:
...
username: root
password: 123
...
Чего же такого плохого в этом файле? А вот чего -- пароль доступа к базе воспринят как число, вместо строки, лечится заключением в двойные кавычки. При этом, будь это строка, кавычек не потребовалось бы. Так что be careful, внимательно читайте маны и stackoverflow.com :-)
Теперь о хорошем. Процесс разработки пока что оставляет положительные впечатления и не кажется трудным.
Отдыхаю после си и жаб и жду появления граблей. :-)
Поскольку использовать sqlite неинтересно,
решил заправить какую-нибудь другую СУБД,
например MySQL.
После непродолжительного, но яркого секса сделал следующие выводы:
1. Устанавливать всякие gem лучше через rvm (Ruby Version Manager).
В этом случае вероятность ошибок, выдаваемых gem, падает в разы.
С gem для установки mysql я вообще совладать не смог.
Он ругался и на отсутствие native libraries, потом сказал, мол не могу получить доступ к памяти,
пару раз ложился с суровым некрологом "Segmentation fault". Так что rvm, однозначно.
Да, поставить rvm с помощью gem мне тоже не удалось, пришлось тащить из git-репозитория.
Соответственно, для rvm, понадобится ещё и git.
2. При генерации базы данных возможны неочевидные ошибки.
Так мне выдалось сообщение, цитирую:
$ sudo rake --trace db:create
...
** Invoke db:create (first_time)
** Invoke db:load_config (first_time)
** Invoke rails_env (first_time)
** Execute rails_env
** Execute db:load_config
** Execute db:create
rake aborted!
can't convert Fixnum into String
...
Ошибка обнаружилась в config/database.yml:
...
username: root
password: 123
...
Чего же такого плохого в этом файле? А вот чего -- пароль доступа к базе воспринят как число, вместо строки, лечится заключением в двойные кавычки. При этом, будь это строка, кавычек не потребовалось бы. Так что be careful, внимательно читайте маны и stackoverflow.com :-)
Теперь о хорошем. Процесс разработки пока что оставляет положительные впечатления и не кажется трудным.
Отдыхаю после си и жаб и жду появления граблей. :-)
- Current Mood:
busy
В выходные развлекался с Ruby on rails.
( Read more...Collapse )
Полезные ссылки:
http://rubyonrails.org, http://rubyforge.org, http://www.rubyonrails.ru
( Read more...Collapse )
Полезные ссылки:
http://rubyonrails.org, http://rubyforge.org, http://www.rubyonrails.ru
На досуге переписал свою же C-реализацию bloom filter с помощью шаблонов C++.
Если посмотреть на уже существующие варианты фильтров, например, Bloom_filter_(C) или OpenBloomFilter, то можно заметить, что для использования на больших объёмах данных они непригодны (под большими объёмами я понимаю тысячи хранилищ по несколько миллионов элементов в каждом). Проблема заключается в попытке включить в фильтр и сам функционал добавления элементов, и хранилище данных, и реализации хэш-функций. Получается красиво, изящно, но это хорошо, когда тепло и пахнет померанцем, а у нас такая философия не по климату. :-)
Для задач промышленных масштабов необходимо выполнение трёх простых условий:
1. Фильтр предоставляет функционал для расчёта параметров и заполнения битовой последовательности; ничего больше.
2. Битовые последовательности, т.е. хранилища данных, создаются независимо от фильтров.
3. Пользователь может использовать различные хэш-функции по своему усмотрению.
Что касается последнего пункта, то для C сигнатура всех функций должна быть одинакова, для C++, за счёт применения шаблонов, возможны вариации с типами аргументов.
Собственно сам фильтр можно посмотреть на github.com/mukhin/libbloom.
P.S. Подумалось, что наверное, кроме мэйла нигде так bloom filter не пользуют, чтобы сотни гигабайт данных, 24x7x365 и 150К запросов в секунду. Поэтому никому и в голову не приходит, что может не хватить памяти, например. :-)
Если посмотреть на уже существующие варианты фильтров, например, Bloom_filter_(C) или OpenBloomFilter, то можно заметить, что для использования на больших объёмах данных они непригодны (под большими объёмами я понимаю тысячи хранилищ по несколько миллионов элементов в каждом). Проблема заключается в попытке включить в фильтр и сам функционал добавления элементов, и хранилище данных, и реализации хэш-функций. Получается красиво, изящно, но это хорошо, когда тепло и пахнет померанцем, а у нас такая философия не по климату. :-)
Для задач промышленных масштабов необходимо выполнение трёх простых условий:
1. Фильтр предоставляет функционал для расчёта параметров и заполнения битовой последовательности; ничего больше.
2. Битовые последовательности, т.е. хранилища данных, создаются независимо от фильтров.
3. Пользователь может использовать различные хэш-функции по своему усмотрению.
Что касается последнего пункта, то для C сигнатура всех функций должна быть одинакова, для C++, за счёт применения шаблонов, возможны вариации с типами аргументов.
Собственно сам фильтр можно посмотреть на github.com/mukhin/libbloom.
P.S. Подумалось, что наверное, кроме мэйла нигде так bloom filter не пользуют, чтобы сотни гигабайт данных, 24x7x365 и 150К запросов в секунду. Поэтому никому и в голову не приходит, что может не хватить памяти, например. :-)
- Current Mood:
занят(а)
Вещь совсем тривиальная и простая как валенок, но пусть будет. Среди наших перловых костылей часто натыкаюсь на скрипты, принимающие на вход целый паровоз безымянных параметров и поди угадай, что бы это значило. Выглядит примерно так: mysupertrouperscript.pl 592 1 1 2010-01-01. Чтобы разобраться в природе всех этих чисел приходится смотреть в исходный код и искать, каким образом обрабатываются входные аргументы. Другая проблема в том, что нельзя изменить порядок следования аргументов, а в некоторых случаях, и исключить какие-то из них.
Решение состоит в замене входных параметров конструкциями вида --argname[=value], разбирать немногим сложнее, зато вызов скрипта становится нагляднее:
В этом разе параметры запуска скрипта более очевидны, а их порядок следования не такой строгий:
mysupertrouperscript.pl --id=592 --date=2010-01-01 --print --debug
Решение состоит в замене входных параметров конструкциями вида --argname[=value], разбирать немногим сложнее, зато вызов скрипта становится нагляднее:
#!/usr/bin/perl
# mysupertrouperscript.pl
# mysupertrouperscript.pl
use strict;
...
my $ID = 0;
my $DATE = '0000-00-00';
my $PRINT = 0;
my $DEBUG = 0;
sub parse_args {
...
my $ID = 0;
my $DATE = '0000-00-00';
my $PRINT = 0;
my $DEBUG = 0;
sub parse_args {
my $f_date = 0;
for (my $i = 0; $i < scalar(@ARGV); $i++) {
for (my $i = 0; $i < scalar(@ARGV); $i++) {
$ID = $1 if ($ARGV[$i] =~ /--id=(\d+)/);
if ($ARGV[$i]=~/--date=(\d{4}-\d{1,2}-\d{1,2} )/) {
$DATE = $1;
$f_date = 1;
}
$PRINT = 1 if ($ARGV[$i] =~ /--print/);
$DEBUG = 1 if ($ARGV[$i] =~ /--debug/);
}
warn "WARNING: date is not defined, $DATE will be used.\n"if ($f_date == 0);
if ($ID == 0) {
warn "ERROR: identifier is not defined.\n";
exit 1;
}
warn "INFO: print mode is on\n" if ($PRINT > 0);
warn "INFO: debug mode is on\n" if ($DEBUG > 0);
}
...
parse_args();
...
if ($ARGV[$i]=~/--date=(\d{4}-\d{1,2}-\d{1,2}
$DATE = $1;
$f_date = 1;
}
$PRINT = 1 if ($ARGV[$i] =~ /--print/);
$DEBUG = 1 if ($ARGV[$i] =~ /--debug/);
}
warn "WARNING: date is not defined, $DATE will be used.\n"if ($f_date == 0);
if ($ID == 0) {
warn "ERROR: identifier is not defined.\n";
exit 1;
}
warn "INFO: print mode is on\n" if ($PRINT > 0);
warn "INFO: debug mode is on\n" if ($DEBUG > 0);
}
...
parse_args();
...
В этом разе параметры запуска скрипта более очевидны, а их порядок следования не такой строгий:
mysupertrouperscript.pl --id=592 --date=2010-01-01 --print --debug
Навеяно замечаниями СБ
Предположим, что есть такой вот фрагмент кода на perl:
my $ID = 0;modifyID($ID);
print "$ID\n" if ($ID > 0);
На первый взгляд условие if ($ID > 0) никогда не выполнится. Действительно, переменная $ID передаётся в функцию по значению, следовательно, по выходе из неё значение переменной останется прежним. Однако, в perl возможно всё. Поэтому то, как показано ниже писать можно, но не нужно, чтобы не пугать гражданское население:
sub modifyID{
$_[0] = 1;
}
В подпрограмме modifyID я обратился непосредственно к $_ элементам массива @_, и произвёл изменения в фактических переменных, передаваемых подпрограмме. Плохо то, что такое поведение подпрограммы абсолютно не очевидно, если не заглядывать в код. Сам же код подпрограммы может находиться совершенно в другом месте и вероятность того, что код скрипта будет "оптимизирован" выбрасыванием якобы никогда не выполняющегося условия очень высока.
Более гуманный способ – заставить передавать значение по ссылке. Код будет выглядеть так:
sub modifyID {
my $ID = shift;
$$ID = 1;
}
Для справки: shift удаляет из массива его первый элемент, сдвигает все оставшиеся в начало и возвращает удаленный элемент в качестве значения. Длина массива сокращается на 1.
Фрагмент кода стал выглядеть немного иначе:
my $ID = 0;
modifyID(\$ID);
print "$ID\n" if ($ID > 0);
Теперь переменная $ID не только передаётся по ссылке, но и при попытке передачи по значению perl выдаст сообщение об ошибке наподобие такого:
Can't use string ("0") as a SCALAR ref while "strict refs" in use at blabla.pl line 6.
Неплохое руководство по написанию подпрограмм нашёл здесь.
- Current Mood:
busy
Один из наших сервисов использует самописный клиент MySQL,
который осуществляет периодический сброс статистики в базу.
Его задача очень простая:
1. проверить состояние соединения с СУБД.
2. если всё Ok, выполнить необходимые запросы.
3. ждать в течение заданного таймаута и повторить п.1,2.
Клиент и сервер MySQL находятся на разных хостах.
Функционал клиента выглядит примерно так:
План тестирования.
1. Ограничения со стороны СУБД.
1.1. Отобрать привилегии у пользователя СУБД и убедиться, что база становится недоступной клиенту.
1.2. Назначить все необходимые привилегии пользователю посредством и убедиться, что соединение с базой восстановлено.
2. Ограничение со стороны FW.
В качестве FW использовался iptables.
Необходимо закрывать/открывать порт соединения с базой и исследовать результаты.
2.1. Порт закрывается до работы клиента.
2.2. Порт закрывается/открывается во время работы клиента.
Основные проблемы обнаружились в MySQL-API.
Смотрим ещё раз на check_db();
Проблема первая: mysql_stat возвращает результат на момент соединения и далее не меняет своего значения.
Замена mysql_stat на mysql_ping привела к зависанию из-за большого таймаута соединения (mysql_ping, как известно, пытается восстанавливать соединение самостоятельно) на условии проверки.
Очевидным решением казалось применение опции таймаута соединения:
Но увы, это породило другую проблему:
В случае, когда порт закрывался до запуска клиента таймаут соединения действительно был равен заданному. Но при проверке п.2.2. клиент опять зависал на строке проверки mysql_ping.
В результате пришлось оторвать проверку напрочь, а функция flash_stat() стала выглядеть следующим образом:
Поскольку периодичность запуска клиента большая, подключение к базе на каждом срабатывании вполне допустимо.
Результаты тестирования.
1. Тестирование доступа к базе на стороне MySQL Server:
1.1.REVOKE ALL PRIVILEGES ON database FROM 'user'@'host';
Записи в логе клиента:
[28.05.2010 19:42:55] flush stat
[28.05.2010 19:42:55] DBconnection closed
[28.05.2010 19:43:00] Connect MySQL failed: Can't connect to MySQL server on 'host'
1.2.GRANT ALL PRIVILEGES ON reklama TO 'user'@'host'
Записи в логе клиента:
[28.05.2010 19:43:55] flush stat
[28.05.2010 19:43:55] DB (user@database) connect OK
[28.05.2010 19:43:55] flush stat OK
2. Тестирование через FW
2.1.
Закрываем порт соединения с базой и запускаем клиент:
/etc/init.d/iptables restart
iptables -A OUTPUT -p TCP --dport 3306 -j DROP
Проверяем, что получилось командой iptables -L -n -v
Записи в логе клиента:
[28.05.2010 19:42:55] flush stat
[28.05.2010 19:42:55] DBconnection closed
[28.05.2010 19:43:00] Connect MySQL failed: Can't connect to MySQL server on 'host'
Открываем порт соединения с базой
iptables -D OUTPUT -p TCP --dport 3306 -j DROP
Записи в логе клиента:
[28.05.2010 19:43:55] flush stat
[28.05.2010 19:43:55] DB (user@database) connect OK
[28.05.2010 19:43:55] flush stat OK
2.2 Повторяем п.2.1., но при работающем клиенте. Результат аналогичен предыдущему.
Мораль этой басни не нова: be careful, при использовании MySQL-API.
который осуществляет периодический сброс статистики в базу.
Его задача очень простая:
1. проверить состояние соединения с СУБД.
2. если всё Ok, выполнить необходимые запросы.
3. ждать в течение заданного таймаута и повторить п.1,2.
Клиент и сервер MySQL находятся на разных хостах.
Функционал клиента выглядит примерно так:
static MYSQL *db;
static void db_disconnect() {
if (db == NULL) return;
mysql_close(db);
db = NULL;
}
static int db_connect() {
if (db)
return 1;
db = mysql_init(NULL);
if (db == NULL) {
log_w("Could not initialize db");
return 0;
}
if (mysql_real_connect(db, ..., NULL, 0) == NULL){
log_w("Connect MySQL failed: %s\n", mysql_error(db));
db_disconnect();
return 0;
}
log_w("DB (%s@%s) connect OK", ssrv_config.db_user, ssrv_config.db_name);
return 1;
}
static int check_db() {
if (db && (mysql_stat(db) == NULL)){
log_w("DBconnection closed");
db_disconnect();
}
if (!db)
db_connect();
if (!db)return 0;
return 1;
}
void flush_stat() {
if (!check_db())
return;
for (...){
// SQL queries
...
}
}
План тестирования.
1. Ограничения со стороны СУБД.
1.1. Отобрать привилегии у пользователя СУБД и убедиться, что база становится недоступной клиенту.
1.2. Назначить все необходимые привилегии пользователю посредством и убедиться, что соединение с базой восстановлено.
2. Ограничение со стороны FW.
В качестве FW использовался iptables.
Необходимо закрывать/открывать порт соединения с базой и исследовать результаты.
2.1. Порт закрывается до работы клиента.
2.2. Порт закрывается/открывается во время работы клиента.
Основные проблемы обнаружились в MySQL-API.
Смотрим ещё раз на check_db();
static int check_db() {
if (db && (mysql_stat(db) == NULL)){
log_w("DBconnection closed");
db_disconnect();
}
if (!db)
db_connect();
if (!db)
return 0;
return 1;
}
Проблема первая: mysql_stat возвращает результат на момент соединения и далее не меняет своего значения.
Замена mysql_stat на mysql_ping привела к зависанию из-за большого таймаута соединения (mysql_ping, как известно, пытается восстанавливать соединение самостоятельно) на условии проверки.
Очевидным решением казалось применение опции таймаута соединения:
#define DBCONNECTION_TIMEOUT 5
...
static int db_connect() {
unsigned int timeout = DBCONNECTION_TIMEOUT;
...
if(mysql_options(db, MYSQL_OPT_CONNECT_TIMEOUT, &timeout)){
log_w("Set options MySQL failed: %s\n", mysql_error(db));
}
...
}Но увы, это породило другую проблему:
В случае, когда порт закрывался до запуска клиента таймаут соединения действительно был равен заданному. Но при проверке п.2.2. клиент опять зависал на строке проверки mysql_ping.
В результате пришлось оторвать проверку напрочь, а функция flash_stat() стала выглядеть следующим образом:
void flush_stat() {
if (!db_connect())
return;
for (...) {
// SQL queries
...
}
db_disconnect();
}
Поскольку периодичность запуска клиента большая, подключение к базе на каждом срабатывании вполне допустимо.
Результаты тестирования.
1. Тестирование доступа к базе на стороне MySQL Server:
1.1.REVOKE ALL PRIVILEGES ON database FROM 'user'@'host';
Записи в логе клиента:
[28.05.2010 19:42:55] flush stat
[28.05.2010 19:42:55] DBconnection closed
[28.05.2010 19:43:00] Connect MySQL failed: Can't connect to MySQL server on 'host'
1.2.GRANT ALL PRIVILEGES ON reklama TO 'user'@'host'
Записи в логе клиента:
[28.05.2010 19:43:55] flush stat
[28.05.2010 19:43:55] DB (user@database) connect OK
[28.05.2010 19:43:55] flush stat OK
2. Тестирование через FW
2.1.
Закрываем порт соединения с базой и запускаем клиент:
/etc/init.d/iptables restart
iptables -A OUTPUT -p TCP --dport 3306 -j DROP
Проверяем, что получилось командой iptables -L -n -v
Записи в логе клиента:
[28.05.2010 19:42:55] flush stat
[28.05.2010 19:42:55] DBconnection closed
[28.05.2010 19:43:00] Connect MySQL failed: Can't connect to MySQL server on 'host'
Открываем порт соединения с базой
iptables -D OUTPUT -p TCP --dport 3306 -j DROP
Записи в логе клиента:
[28.05.2010 19:43:55] flush stat
[28.05.2010 19:43:55] DB (user@database) connect OK
[28.05.2010 19:43:55] flush stat OK
2.2 Повторяем п.2.1., но при работающем клиенте. Результат аналогичен предыдущему.
Мораль этой басни не нова: be careful, при использовании MySQL-API.
- Current Mood:
busy
Если бы мне кто-нибудь сказал, что я буду слушать лекцию создателя STL да ещё в Москве, да ещё и на русском языке, я бы наверное не поверил. Но вот вчера случилось фантастическое для меня событие — я сидел в самом логове Яndex и слушал того самого Степанова, который дружит с Мёртвым Страусом и Виртом, к которому, по его, на лекции захаживает Дональд Кнут и который.
Лекция была посвящена истории развития алгоритма вычисления GCD (НОД), начиная со времён Пифагора, когда не знали такой цифры, как 0, отрицательных чисел и деления с остатком, и заканчивая нашими 90-ми, когда голландские математики установили, что современная версия алгоритма позволяет вычислять gcd для любых типов данных будь то десятичные числа или полиномы. Наверное неправильно говорить, что лекция только про gcd. Мне кажется, что основная задача была заронить мысль, что все программисты прежде всего - математики, поскольку в конечном итоге отображают все свои задачи на множества чисел, поэтому в первую очередь необходимо работать в этом направлении, изучить базис и понять архитектуру, а не хвататься за "154 новых рецепта программирования на каком-то-там-языке-программирования". Но при этом ни в коем случае не отделять теорию от практики (хороший пример - "Игра в бисер" Германа Гессе). Кстати о рецептах, прозвучала сентенция примерно такая: "Три года назад, когда вы были юными, вы всё это изучали и знали... Потом вы устроились на работу и начали читать Александреску. Ну что сказать, не читайте Александреску, читайте Евклида и Дональда Кнута." :-)
Вообще Александр Александрович Степанов — замечательный оратор с превосходным чувством юмора и завидной эрудицией. Я завидую американским и европейским ребятам, в чьих университетах он читает лекции. Я давно не слышал таких лекций, которые не просто вводят в курс дела, но указывают правильный вектор развития и мощный пинок под зад.:-)
Полезные ссылки:
Лекция была посвящена истории развития алгоритма вычисления GCD (НОД), начиная со времён Пифагора, когда не знали такой цифры, как 0, отрицательных чисел и деления с остатком, и заканчивая нашими 90-ми, когда голландские математики установили, что современная версия алгоритма позволяет вычислять gcd для любых типов данных будь то десятичные числа или полиномы. Наверное неправильно говорить, что лекция только про gcd. Мне кажется, что основная задача была заронить мысль, что все программисты прежде всего - математики, поскольку в конечном итоге отображают все свои задачи на множества чисел, поэтому в первую очередь необходимо работать в этом направлении, изучить базис и понять архитектуру, а не хвататься за "154 новых рецепта программирования на каком-то-там-языке-программирования". Но при этом ни в коем случае не отделять теорию от практики (хороший пример - "Игра в бисер" Германа Гессе). Кстати о рецептах, прозвучала сентенция примерно такая: "Три года назад, когда вы были юными, вы всё это изучали и знали... Потом вы устроились на работу и начали читать Александреску. Ну что сказать, не читайте Александреску, читайте Евклида и Дональда Кнута." :-)
Вообще Александр Александрович Степанов — замечательный оратор с превосходным чувством юмора и завидной эрудицией. Я завидую американским и европейским ребятам, в чьих университетах он читает лекции. Я давно не слышал таких лекций, которые не просто вводят в курс дела, но указывают правильный вектор развития и мощный пинок под зад.:-)
Полезные ссылки:
- здесь можно найти старую версию конспекта лекции в PDF-формате:http://www.stepanovpapers.com/
- в блогах Яndex следим за публикацией видео и слайдов презентации лекции: clubs.ya.ru/company/replies.xml, yandex.livejournal.com/60892.html
- книжка Elements of Programming www.elementsofprogramming.com/book.html
Comments
но статья…
Кстати, есть такая классная тётка, Лапонина Ольга Германовна, она в МГУ преподаёт. У неё есть учебник по протоколам безопасного сетевого взаимодействия, и там…
нет, на винде.
Извините за глупые вопросы, если что.