Видео докладов с конференции IT NonStop Воронеж 2015

Привет, Хабр!

Совсем недавно завершился воронежский этап отличной международной конференции IT NonStop 2015. Перед гостями выступили отличные спикеры с докладами на самые разные темы. Сегодня мы хотели бы поделиться с вами видео с выступлений.

ссылка на оригинал статьи http://habrahabr.ru/post/254657/

Coub идет на Стачку

10-11 апреля в Ульяновске состоится крупнейшая в регионах России IT-конференция «Стачка». Coub ходил на Стачку в прошлом году, не смог пропустить ее и в этом. Мы не только будем на ней присутствовать, но и привезем с собой несколько докладов.

Стачка 2015

Мы выступим с докладами в 3-х секциях

  • Техническая
  • Менеджмент и образование
  • Мобильная разработка

Правила отличного разработчика

В первый день конференции Михаил Табунов расскажет, что значит быть хорошим разработчиком:

imageТабунов Михаил, CTO

Хороших и отличных разработчиков разделяет совсем немного качеств, тем не менее разница в результатах их работы порой очень большая. Дело тут не в эрудированности и каких-то личных качествах, а только в понимании ценностей. У разработчика они одни, у его руководства другие. Очень редко бывает когда они совпадают. Его доклад попробует объяснить, к чему надо стремиться в работе, и что за это будет.


Наложение видеоэффектов с GPU оптимизацией при помощи OpenGL ES 2.0 with Shaders

imageМаксим Решетей, Lead iOS developer

Максим расскажет о том, как работает наложение видеоэффектов в реальном времени в мобильном приложении Coub c использованием OpenGL ES 2.0 with Shaders. С оптимизацией под GPU архитектуру.

Детали доклада

1. Цифровая обработка видео и изображений, теоретические основы и общий алгоритм.
3. Примеры вычислений некоторых простейших фильтров.
4. Размытие по Гауссу, теоретические основы и общий алгоритм.
5. Оценка эффективности на CPU.
6. Графические процессоры (GPU) и особенности их архитектуры.
7. Оценка эффективности размытия по Гауссу на GPU.
8. Графическая библиотека OpenGL ES и шейдерное программирование.
9. Эффективная реализация размытия по Гауссу при помощи пиксельного шейдера.


Как мы сбежали от PostgreSQL или когда реляционная БД не справляется

imageКуманяев Андрей, Ruby on Rails developer

Большое количество данных — это здорово.
Сложная бизнес логика — интересно.
Работает быстро — прекрасно!
Выкинешь какой-нибудь пункт — идеально.

Расскажу о том, что случилось, как решали проблемы и к чему, в итоге, пришли.

Это самый покрытый тайной доклад от нас. Приходите, обсудим то, каково это ворочать большим количеством данных в PostgreSQL.

И не забудьте про кулуарную часть конференции, где можно завязать много полезных знакомств. В конце первого дня вас ждет закрытая афтепати в компании спикеров и коллег по цеху.

Программа конференции и билеты на сайте nastachku.ru.

ссылка на оригинал статьи http://habrahabr.ru/post/254549/

«Собери 3 сердца, 3 черепа и 3 меча одним сдвигом», или как мы делали игру

Статья будет представлять собой описание вещей, которые мы сами не знали до начала разработки, и которыми хотелось бы поделиться с начинающими и не очень разработчиками. На данный момент у нас 200 активных игроков в день, каждый день добавляется еще от 10 до 50, всего зарегистрировано около 5 тысяч. За все время игра принесла порядка 1000$.

О чем игра

Сначала мы решили портировать БК (одна из первых браузерных MMORPG) на телефон, но в процессе идея эволюционировала. Закончили match-3 игрой с элементами RPG и возможностью PvP. В общем, смесь «БК», «Candy Crush» и «Небеса». Игрок воюет с монстрами, развивается, делает квесты, покупает вещи и свитки магии. Бой проходит в поочередном режиме в стиле match-3 с разными кристаллами — лечение, яд, усиление и т.д. Главное новшество — бои с людьми, можно драться со случайными противниками или добавлять друзей и драться с ними.


Небольшая техническая врезка, с полным списком программ и технологий. Кому интересно

Дизайн
Первые версии интерфейса были нарисованы в Balsamiq Mockups — очень удобный инструмент для быстрых набросков дизайна. В нем же рисовали и схемы переходов между экранами:

Клиент
Клиент писали на Objective-C. Трехмерной графики и сложной анимации у нас нет, да и цена большинства фреймворков нас смущала. Мака в нашем распоряжении не было, поэтому на первых порах использовали эмулятор VMware. Как сейчас помню первую запущенную программу — белый фон с распечатанным текстом Zhopa «Hello, world!».
Спустя полгода мы-таки раскошелились на Mac. Билд на нем работает раз в 10 быстрее, поэтому если вы пишете серьезный проект, стоит задуматься о покупке хотя бы Mac mini с самого начала.

Сервер
Сервер писали на PHP, раньше был опыт работы с ним. Для Version control выбрали Assembla. Особенно порадовало, что в связке с Netbeans, на котором мы писали, он встал без запинки.
Базу данных сначала делали на MySQL, таблицы и связи строили в MySQL Workbench, и работали с этим всем через PDO.
Спустя полгода мы решили освоить новую технологию и переписать весь DAL на noSQL. Выбрали MongoDB в виду относительной распространенности и простоты. Книжка “The Little MongoDB book”, не смотря на свои скромные 30 страниц, дает хорошую отправную точку.
Хостинг взяли на Amazon. При всем удобстве у амазона есть ощутимый минус — цена. При практически нулевом траффике получается порядка 200 долларов в год за один вычислительный микро сервер ec2 и одно хранилище s3.

Бета тест
Закачивать игру тестерам на телефоны через Xcode неудобно, и главное, нельзя делать это удаленно. Тут выручил сервис TestFlight, который позволяет устанавливать игру удаленно еще во время разработки.
Кроме поиска багов нужно было получить отзывы по геймплею и интерфейсу. Мы сделали список вопросов и оформили опросом в SurveyMonkey. Простенькая система для опросов, бесплатная и с удобным доступом к результатам.
Одновременно мы послали игру в аппстор на проверку, чтобы потом не терять времени, так как они часто просят что-то переделать. Каково же было наше удивление, когда через 10 дней мы получили аппрув с первого раза.

Итак, приступим.

1. Экономика, статы вещей, балансировка боя и все, что входит в понятие «геймплей»

В играх такого типа геймплей отнимает просто уйму времени и начать заниматься этим надо как можно раньше. Самое главное — делать все очень системно. Сначала мы что-то делали на глазок, например, параметры оружия, но быстро осознали масштаб проблемы. Закончилось все огромными таблицами в Excel, автоматически высчитывающими все на свете. Ничего удобнее, чем Excel, для этих целей мы, кстати, так и не нашли.

Была идея найти геймдизайнера на стороне, но один умный человек сказал: «Хотите вы или нет, но вам придется вырастить геймдизайнера у себя». Оглядываясь назад, мы понимаем, что он имел ввиду.

Есть отличная статья для начинающих, приводит голову в порядок и объясняет, как это все делается по уму (на английском). Еще можно почитать на Gamasutra статьи Рамина Шакридзе, очень много дает в плане понимая геймплея. Несколько переводов его статей есть и на Хабре.

2. Achievements

Много времени заняло придумать нормальную систему достижений, самая, на мой взгляд, толковая статья (на английском).

Не стоит недооценивать важность достижений, это целая наука и немало хороших игр были загублены непродуманными действиями геймдевов. Одно и то же задание может превратиться как в квест с наградой, так и в достижение без. Важно понимать разницу в психологии восприятия и сделать выполнение максимально позитивным.

3. Рейтинги игроков

Поначалу пытались придумать что-то свое, но потом стало понятно, что изобретаем велосипед. Тут на помощь пришла статья «Как правильно сортировать контент на основе оценок пользователей». После прочтения радостно сообщил команде, что теперь «рейтинг высчитывается по нижней границе доверительного интервала Вильсона для параметра Бернулли».

4. Аналитика

Для аналитики использовали Flurry и Google Analytics. У каждой из систем свои плюсы и минусы, только об одном этом можно написать целую статью. Если вкратце, Flurry дает возможность сделать до 300 типов событий, с кучей параметров в каждом. А Google позволяет сделать бесконечное количество типов событий, но всего с одним параметром. Кстати, из разговоров с издателями мы узнали, что они тоже обычно используют больше одной системы аналитики — как одновременно, для перестраховки, так и по отдельности, в тех случаях когда одна удобнее, чем другая.

Замеряли мы, во-первых, собственные метрики, например, с какого раза игроки проходят каждого монстра. И, во-вторых, общепринятые показатели, которые спрашивают издатели — MAU, DAU, ARPU, ARPPU, ARPDAU, K-factor, 2/7/28 day retention.

5. Обучение

Одним из главных нареканий издателей было отсутствие обучения. Из личного опыта: самые лучшие туториалы — интерактивные. Здесь главное — найти золотую середину, чтобы их не было слишком много, но в то же время объяснялся основной функционал. При достаточном упорстве можно заставить туториал вести себя не так, как планировалось, что может привести к зависанию. Чтобы отслеживать проблемные места, мы добавили события аналитики на начало и конец каждого туториала.

6. Локализация

Изначально включили языки с максимальным охватом аудиторий — испанский, французский, итальянский, немеций и, конечно, русский. Перевод был нужен качественный, поэтому заказывать дешево и сердито, например, на fiverr мы не решились, вместо этого обратились в Globaloc.de, специализирующимся на переводе игр. Остались очень довольны, хотя ценник немного кусается, около 10 центов за слово.

7. Бот

Монстры в игре играют в match-3, пытаясь убить игрока. Для написания бота мы использовали алгоритм Minimax.

Писали итеративно, каждый раз применяя разные стратегии и сравнивая. Даже ставки делали, какая версия бота победит. В какой-то момент заигрались и монстры начали выбирать такой ход, чтобы оставить противнику наихудшее поле. Оказалось, что писать слишком умного бота нельзя, начинает казаться, что он тот еще жулик, и заранее знает какие камни упадут, хотя это и не так. Чтобы сделать сложного монстра интересным, лучше добавить ему статов, и оставить алгоритм, сопоставимый с тем, что может просчитать живой человек.

8. Content Management System

Очень полезна возможность — делать простые обновления без того, чтобы перезаливать клиент на AppStore. Для этого написали CMS — при каждом подключении клиент сверяется с сервером, и при необходимости докачивает нужные данные. Теперь можно добавлять в игру оружие и целые локации, не перезаливая клиент.
Хотя все проблемы при передаче и битые пакеты должны лежать на плечах TCP, у нас были ситуация, когда на клиенте оказывались наполовину загруженные картинки. Дописали ручную проверку, после скачивания клиент высчитывает md5 полученных данных, сравнивает и при необходимости перезакачивает.

9. Размер приложения

В AppStore есть ограничение на размер приложений, которое можно скачивать через 3G или EDGE. Этот размер является важным критерием и может ощутимо повлиять на количество установок. Наша игра со всей графикой переваливала за разрешенную границу, поэтому чтобы уложиться в заветные 50 МБ, нам пришлось сделать систему фоновой догрузки графики (на момент разработки разрешение было 50 МБ, сейчас подняли до 100). В начальной сборке вшито только 2 локации, остальные монстры и локации докачиваются на фоне по мере прохождения с помощью CMS.

10. Обратная связь и Help

Возможность написать разработчикам прямо из игры очень важна. Если игрок хочет дать совет или пожаловаться на баг, он должен иметь возможность сделать это прямо из игры. В противном случае он напишет это в ревью на аппсторе, и количество звезд в отзыве скорее всего будет меньше, чем на дорогом коньяке. А чем лучше будет ваш Help, тем меньше игроки будут посылать вам вопросов. Для этих целей мы встроили SDK от uservoice.com Они дают возможность динамически менять Help и при желании сделать хоть целую энциклопедию. В той же системе можно отправить и отзыв разработчикам.

11. Иконка игры

С одной стороны, можно было отдать матерому художнику, специализирующемуся на иконках и висящему в топах на сайтах вроде dribbble.com. Связывались, стоит порядка 1500$. В итоге обратились к нашему художнику и денег потратили в 10 раз меньше, и результатом остались очень довольны.

12. Графика
Всю графику заказывали аутсорсом. Изначально была мысль сделать игру только под iPhone, но оказалось, что около половины прибыли игр приходится на iPad, это изменило нашу мысль. Вывод — лучше сразу заказывать всю графику в высоком разрешении, разница в цене небольшая.

Вся графика стоила порядка 20.000$ — более 40 полноразмерных персонажей и монстров, десятки локаций, вещей, ачивок и т.д.

За время разработки сменилось около 10 художников, в итоге заканчивали с 3 постоянными, каждый из которых отвечал за свой фронт работ.

Заказать графику такого проекта под ключ у студии будет стоить от 50.000$. Вывод: иметь художника в команде очень круто.

13. Музыка

Мы заказали у композитора комплект звуков для всех действий в игре и две главных музыкальных темы — в бою и вне боя. Очень интересный опыт. Сложно объяснить в техзадании, как вот та кнопка должна «клацать», а для описания музыки в бою эпитета «героическая» оказывается недостаточно.

Озвучка, по сравнению с графикой, стоила совсем недорого, порядка 500$.

14. Издатели

С самого начала мы решили, что будем выпускаться при помощи паблишера. Сделав трейлер и презентацию, мы разослали их 20-ти самым крупным издателями. Ответили треть, среди них были Chillingo, BigFish и Alawar. Из того, что предлагали нам, доля паблишера составляет 35-50% от чистой прибыли, после вычета комиссии Apple и прямых затрат на покупку траффика (если игроки приводятся не из других игр издателя). Большинство просили рабочую демку на TestFlight. Некоторые написали подробные отчеты о наших недостатках, поэтому написать издателям уже на этапе разработки в любом случае полезно.

Ни с кем из хороших издателей договориться сразу не получилось, поэтому мы решили сами делать Soft Launch — запуск на маленьких рынках с целью отточить геймплей и монетизацию. Нужны были небольшие англоязычные рынки, поэтому были выбраны Австралия, Н.Зеландия и Малайзия.

Мы увидели 2 основных пути работы с издателями:
1. Связаться еще на этапе разработки. Издатели могут очень помочь с геймплеем и монетизацией. Плюс мотивация, что в этом мире есть кто-то еще, кто заинтересован в успехе игры.
2. Полностью закончить игру, сделать Soft Launch, собрать метрики и отточить игру. И уже с цифрами обратиться к издателям. В случае хороших показателей сможете получить более выгодные условия. Сложность заключается в том, что нужно самим набрать критическую массу игроков.

Вот вроде и все, если что-то вас особенно заинтересовало, пишите в комментариях, с удовольствием расскажу подробней.

И напоследок немного о нас

Мы команда из 4 человек, и это наша первая игра. Разделение было таким:
Дизайн — 1 креативщик
Клиент — 1 программист
Сервер — 1.5 раздолбая
Геймплей — 0.5 человека

Собрав в кучу первые буквы фамилий, мы стали называться Ekza. Самое важное это конечно нарисовать фирме логотип, на что мы в свое время потратили целый день.

Первый эскиз логотипа и его конечный вариант:

Работали мы практически все выходные на протяжении двух лет, плюс пару часов каждый день после работы. То есть фактически это примерно год 5-ти дневной работы 4-х человек.

В завершение еще пару примеров начальных набросков и конечных результатов.

Бой

Рюкзак

ссылка на оригинал статьи http://habrahabr.ru/post/254649/

Пример простейшего cgi сервера

Думаю многие знают, как работает CGI взаимодействие между клиентом и сервером: клиент получает от сервера и отдает серверу данные через стандартные stdin и stdout. Многие наверное даже сами писали CGI клиентов, ведь по сути — любой скрипт для веб-сервера это и есть CGI-клиент.
А многие ли задавались вопросом, как именно происходит эта «магия»? Каким образом стандартные функции для ввода/вывода вместо экрана взаимодействуют с сервером?

Результаты поиска ответа в сети меня не удовлетворили и я решил сам написать простейший CGI сервер, который сможет:

  • Запускать дочерний процес — CGI скрипт
  • Передавать скрипту переменные окружения и переменные командной строки
  • Принимать от скрипта ответ
  • Завершаться, когда завершится процесс клиента

Кроме этого, мне хотелось, чтобы клиент и сервер компилировались как в Windows, так и в Linux.

CGI-клиент

Начну я все-таки с самого простого и общеизвестного: опишу своего клиента для CGI сервера. Простой «hello world» меня не устроил, потому что нужно было проверить не только возможность передачи сообщений через stdout, но и корректность приема переменных окружения и сообщений из stdin.
Кроме этого чтобы убедиться, что получилось самое настоящее CGI взаимодействие, было решено написать не один, а сразу два клиента. На с++ и на python.

Исходник CGI-клиента на С++

#include <stdio.h> #include <stdlib.h> #include <iostream> #include <fcntl.h> #include <vector>  #ifdef _WIN32 #include <windows.h> #define getpid() GetCurrentProcessId() #define sleep(n) Sleep(n*1000); #else #include <unistd.h> #endif  using namespace std;  int main(int argc, char *argv[]) { 	//Отдаем в stdout переменные командной строки, которые получили от родителя 	cout << "Child process started\n"; 	for (int n=0; n<argc; n++) 		cout << "argv[" << n << "] = " << argv[n] << "\n";  	//Отдаем в stdout переменные окружения, которые получили от родителя 	const int nContentLength = atoi(getenv("Content-Length")); 	cout <<  		"\n" <<  		"Content-Length = " << nContentLength << "\n" << 		"VARIABLE2 = " << getenv("VARIABLE2") << "\n" << 		"VARIABLE3 = " << getenv("VARIABLE3") << "\n" << 		"\n\n"; 	fflush(stdout);  	sleep(5); //Паузы сделаны для наглядности  	vector<unsigned char> vBuffer(nContentLength);  	//Получаем из stdin все, что прислал туда родительский процесс     const size_t nBytes = fread(&vBuffer[0],  1, nContentLength, stdin);  	//Отдаем в stdout то, что только что получили от родителя и добавляем свое 	cout << "Request body:\n";     fwrite(&vBuffer[0], 1, nBytes, stdout);     fflush(stdout);  	sleep(5); //Паузы сделаны для наглядности  	return 0; } 

Исходник CGI-клиента на Python

#!/usr/bin/python  import sys import os  print "Content-Length = " + os.environ["Content-Length"] print "VARIABLE2 = " + os.environ["VARIABLE2"] print "VARIABLE3 = " + os.environ["VARIABLE3"]  body = sys.stdin.read( int(os.environ["Content-Length"]) ) print body  

Пояснения к коду клиентов

Если из CGI-сервера запустить клиента на С++, то на экран выведется информация о переменных командной строки, три переменные окружения с именами «Content-Length», «VARIABLE2» и «VARIABLE3», а также все содержимое которое получено от сервера в stdin.
Если из CGI-сервера запустить клиента на Python, то на экран выведется информация о переменных окружения с именами «Content-Length», «VARIABLE2» и «VARIABLE3», а также все содержимое которое получено от сервера в stdin.

Надо отметить, что переменная окружения «Content-Length» должна быть сформирована сервером таким образом, чтобы быть числом меньше либо равным количеству байт в stdin. Это необходимо потому, что клиент никаким другим образом не может узнать данную информацию кроме как от сервера.

CGI-сервер

В отличии от клиентских скриптов, код CGI сервера в сети найти совсем не просто, поэтому мой код собран из различных обрывистых и часто содержащих ошибки примеров. Кое-что добавил от себя, чтобы было более наглядно.

Исходник CGI-сервера на С++

#include <stdio.h> #include <iostream> #include <fcntl.h> #include <string> #include <vector>  #ifdef _WIN32 #include <process.h> /* Required for _spawnv */ #include <windows.h> #include <io.h>  #define pipe(h) _pipe(h, 1024*16, _O_BINARY|_O_NOINHERIT) #define getpid() GetCurrentProcessId() #define dup _dup #define fileno _fileno #define dup2 _dup2 #define close _close #define read _read #define write _write #else #include <errno.h> #include <unistd.h> #include <signal.h> #include <sys/wait.h> #endif  using namespace std;  //Формируем в глобальных переменных тело запроса и его длинну static const string strRequestBody = "===this is request body===\n"; static const string strRequestHeader = "Content-Length=" + to_string((long long)strRequestBody.length());  //Формируем переменные окружения которые будут отосланы дочернему процессу static const char *pszChildProcessEnvVar[4] = {strRequestHeader.c_str(), "VARIABLE2=2", "VARIABLE3=3", 0};  //Формируем переменные командной строки для дочернего процесса. Первая переменная - путь к дочернему процессу. static const char *pszChildProcessArgs[4] = {"./Main_Child.exe", "first argument", "second argument", 0}; //При желании можно запустить интерпретатор какого-нибудь скрипта.  //Тогда первый аргумент - путь к интерпретатору, второй - к скрипту //static const char *pszChildProcessArgs[3] = {"python", "./test.py", 0};  //Это функция, которая породит дочерний процесс и передаст ему переменные из родительского int spawn_process(const char *const *args, const char * const *pEnv) { #ifdef _WIN32 	return _spawnve(P_NOWAIT, args[0], args, pEnv); #else     /* Create copy of current process */     int pid = fork();          /* The parent`s new pid will be 0 */     if(pid == 0)     { 		/* We are now in a child progress  		Execute different process */ 		execvpe(args[0], (char* const*)args, (char* const*)pEnv);  		/* This code will never be executed */ 		exit(EXIT_SUCCESS); 	}      /* We are still in the original process */     return pid; #endif     }  int main() { 	int fdStdInPipe[2], fdStdOutPipe[2]; 	 	fdStdInPipe[0] = fdStdInPipe[1] = fdStdOutPipe[0] = fdStdOutPipe[1] = -1; 	if (pipe(fdStdInPipe) != 0 || pipe(fdStdOutPipe) != 0) 	{ 		cout << "Cannot create CGI pipe"; 		return 0; 	}  	// Duplicate stdin and stdout file descriptors 	int fdOldStdIn = dup(fileno(stdin)); 	int fdOldStdOut = dup(fileno(stdout));  	// Duplicate end of pipe to stdout and stdin file descriptors 	if ((dup2(fdStdOutPipe[1], fileno(stdout)) == -1) || (dup2(fdStdInPipe[0], fileno(stdin)) == -1)) 		return 0;  	// Close original end of pipe 	close(fdStdInPipe[0]); 	close(fdStdOutPipe[1]);  	//Запускаем дочерний процесс, отдаем ему переменные командной строки и окружения 	const int nChildProcessID = spawn_process(pszChildProcessArgs, pszChildProcessEnvVar);  	// Duplicate copy of original stdin an stdout back into stdout 	dup2(fdOldStdIn, fileno(stdin)); 	dup2(fdOldStdOut, fileno(stdout));  	// Close duplicate copy of original stdin and stdout 	close(fdOldStdIn); 	close(fdOldStdOut);  	//Отдаем тело запроса дочернему процессу 	write(fdStdInPipe[1], strRequestBody.c_str(), strRequestBody.length());  	while (1) 	{ 		//Читаем ответ от дочернего процесса 		char bufferOut[100000]; 		int n = read(fdStdOutPipe[0], bufferOut, 100000); 		if (n > 0) 		{ 			//Выводим ответ на экран 			fwrite(bufferOut, 1, n, stdout); 			fflush(stdout); 		}  		//Если дочерний процесс завершился, то завершаем и родительский процесс #ifdef _WIN32 		DWORD dwExitCode; 		if (!::GetExitCodeProcess((HANDLE)nChildProcessID, &dwExitCode) || dwExitCode != STILL_ACTIVE) 			break; #else 		int status; 		if (waitpid(nChildProcessID, &status, WNOHANG) > 0) 			break; #endif 	} 	return 0; }

Пояснения к коду сервера

Сервер писался так, чтобы его можно было скомпилировать как в Windows, так и в Linux, поэтому первые несколько строк это кроссплатформенные определения.
Дальше в глобальных переменных задается:

  • тело запроса который будет послан скрипту (строка "===this is request body===\n"), длина сообщения запоминается в переменной strRequestHeader
  • переменные окружения в виде массива строк {strRequestHeader.c_str(), «VARIABLE2=2», «VARIABLE3=3», 0}
  • переменные командной строки в виде массива {"./Main_Child.exe", «first argument», «second argument», 0}

При такой инициализации сервер будет взаимодействовать с процессом "./Main_Child.exe". Так я назвал скомпилированного клиента на С++.
Если в качестве переменных командной строки задать массив {«python», "./test.py", 0}, то сервер будет взаимодействовать со скриптом на питоне.

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

Заканчивается сервер функцией «main», большую часть которой (как можно догадаться по английским комментариям) я взял из разных сторонних источников. Из кода этой функции видно, что «вся соль» перенаправления ввода/вывода между процессами организована с помощью «pipe» (каналов).
Механизм каналов довольно простой и стандартный, он почти одинаково реализован как в Windows так и в Linux. Чтобы связать эти два подхода, в самом начале исходника я добавил простое переопределение:

#ifdef _WIN32 #define pipe(h) _pipe(h, 1024*16, _O_BINARY|_O_NOINHERIT) #endif 

В конце функции «main» организован бесконечный цикл, в котором сервер принимает от клиента ответ и передает этот ответ на экран. Выход из цикла произойдет когда клиентский процесс завершится.

Заключение

Несмотря на свой солидный возраст, CGI — интерфейс остается одним из самых распространенных интерфейсов межпроцессного взаимодействия. Подавляющее большинство веб-серверов и веб-сайтов взаимодействуют именно с помощью этого интерфейса. Надеюсь данная статья будет полезна тем, кто захочет понять, а может и реализовать в собственных проектах не только клиентскую, но и серверную часть CGI.

Все исходники можно найти: тут.
В папках «cgi_main» и «child» находятся проекты для Visual Studio.
Чтобы запустить пример под Линукс, достаточно скопировать содержимое папки «src» и запустить скрипт «compile.py». Должно получиться что-то вроде этого:

ссылка на оригинал статьи http://habrahabr.ru/post/254621/

Сто раз одно и то же

image

История этого шуточного эксперимента начинается ровно с того момента, когда моя неспокойная голова, глядя на процесс работы техподдержки и других случаев обработки большого потока запросов, задалась вопросом пересмотра такого аспекта в более игровую сторону: «Что если кучу запросов вручную разбрасывать в какие-то тематические корзины наподобие вещей перед стиркой или мусора перед контейнерами?»

Условие задачи – вопрос на ответ

После шлифовки условий задачи прояснилась и суть будущего эксперимента: типичный вопрос ждёт не вручную написанный ответ, а заброс в корзину типичного ответа или складывание вилки ответа из шаблонных фраз.
image
Рис. 1 Шаблонному вопросу – шаблонная корзина

Этапы процесса в таком случае не новы: разделены на пользовательскую и модераторскую часть, представлены формированием запроса (1), попаданием его в необработанный поток (2), который сортируется модератором по корзинам (3), проверяется и подтверждается (4) для оповещения (5) и публикации (6).
image
Рис. 2 Этапы процесса

С точки зрения пользователя ничего нового нет: после ознакомления с текущими постулатами, которые разбиты на темы, пользователь, не найдя ответ на свой вопрос, формирует запрос (1) и, после некоторого ожидания, получает ответ (5). Помимо этого, можно предусмотреть сбор и публикацию однотипных запросов (6), если на то будут какие-то причины.
image
Рис. 3 Пользовательский сценарий

Модераторский сценарий предполагает необработанный поток (2) раскидывать по существующим или формируемым по ходу дела корзинам (3), проверку и публикацию результатов (4).
image
Рис. 4 Модераторский сценарий

Идей для абстрактного примера, чтобы пощупать и отшлифовать эту концепцию, пришло несколько: приёмная депутата, поп-звезды или военкомата. Были и другие варианты, но остановится я решил на всплывших воспоминаниях об одном персонаже, которому тоже не помешала бы удобная админка по рассортировке нескончаемого входящего потока.

Приёмная Брюса

Как справиться с нахлынувшим потоком молитв, когда на тебя неожиданно сваливаются обязанности Всемогущего? Брюс Нолан, персонаж Джима Керри в фильме «Брюс Всемогущий», пробовал картотеку и стикеры, но в итоге решил воспользоваться высокими технологиями. Опираясь на своё небольшое исследование, я решил сделать свою версию админки для Брюса.

Итак, после того как пользователь отправляет запрос, сообщение попадает в приёмную Брюса, которая может выглядеть примерно так:

2.1.1 Моментальный режим

Если режим работы приложения (по умолчанию «моментальный»: ответы сразу отправляются и публикуются) переключается на «накопительный» (ответы копятся и спускаются по команде) – внизу страницы появляется панель сессии:

1.2 Накопительный режим

Чтобы лучше понять ситуацию, Брюс может почитать молитву полностью или глянуть профиль:

2.1 Развёрнутая молитва

image

После этого он может складывать шаблонный ответ из тех, что на виду…

3.1 Сложенный ответ

… редактируя по желанию любой массив текста, нажав на него…

3.3 Добавление нешаблонного массива

… или дополняя сообщение нешаблонным массивом через клик на свободное место в текстовом поле или по кнопке «Дописать весть»:

3.2 Редактирование массива

Если какой-то ответ начинает повторяться не один раз — назревает новый шаблон, который можно по-быстрому создать или по кнопке «Создать шаблон» …

4.1 Быстрое создание шаблона

… или в редакторе шаблонов по ссылке «Все шаблоны», где можно существующие шаблоны отредактировать или перетащить в шорт-лист популярных:

4.2 Все шаблоны

Сделать шаблонными можно не только короткие фразы, но и объёмы побольше, чтобы Брюс рассказал, скажем, какую-нибудь притчу:

4.3 Новый сложный шаблон

Если случай неоднозначный, можно перенаправить запрос или отложить решение на потом:

5.1 Перенаправить на диавола

5.2 Послать испытание

Отображение панели шаблонов можно настроить под себя:

6.1 Менюшки панели шаблонов

6.2 Вид рядами

В зависимости от случая, новоиспечённый Всемогущий сможет публиковать ответ на сайте или выслать оповещение приватно…

7. Личное и приватное

… а в случае с накопительным режимом – проверить сформированные ответы перед массовой отправкой:

8. Проверка сессии

Несмотря на могущество, наверняка будут промахи или желание подкорректировать панель, поэтому в приёмной можно воспользоваться настройками, заточив её под себя или откатив базу ответов до нужного состояния:

9. Настройки

Вот таким выдался концепт, начавшийся с желания попробовать какой-нибудь игрушечный функционал складывания сообщений. На этом мой рассказ сказывается, ваши комментарии — приветствуются.

ссылка на оригинал статьи http://habrahabr.ru/post/254017/