Издательский дом ООО "Гейм Лэнд"ЖУРНАЛ ХАКЕР #62, ФЕВРАЛЬ 2004 г.

Instant Messaging: строим свой клиент

Косякин Антон

Xakep, номер #062, стр. 062-118-1


(deil@real.xakep.ru)

Моделируем свой гиперклиент

Доброго времени суток! Надеюсь, ты прочитал мою предыдущую статью по этой теме? Понравилась? Нет? (Привет, Токса! 8)) Ну и ладно. Сейчас мы обсудим более интересный вопрос - проектирование и написание клиентской части IM. Клиент – это именно та вещь, по которой конечный пользователь и будет оценивать твою программу. Сначала он посмотрит на оформление, дизайн, простоту и удобство работы, а потом уже будет оценивать функциональность и надежность передачи данных, обеспечиваемые сервером. Итак, приступим!

О реализации

В очередной раз советую в качестве языка программирования выбрать С/С++. И разделить программу на два модуля: передача данных + GUI. Причем передачу данных предлагаю написать с соблюдением максимального количества стандартов, без использования Windows-специфичных функций, и оформить этот модуль как shared library (DLL). Графическую же часть лучше написать на каком-нибудь Borland C++ Builder’а (или Qt Designer'а). Таким образом отпадет необходимость переделывать весь клиент при изменении его «транспортной» части - в готовом проекте необходимо будет просто заменить библиотеку. Также можно будет легко написать GUI, не вдаваясь в подробности реализации сетевой части клиента. И главный плюс такого подхода - код этой библиотеки можно будет легко использовать на разных платформах, причем с минимальными изменениями.

Еще немного о передаче данных

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

Суть ее вот в чем: вместе с каждым пакетом передаем его ID, идентификатор и число. Изначально, при инициализации работы сервера с клиентом, необходимо выбрать этот ID случайным образом. А затем, при отправке каждого нового пакета, увеличивать его на единицу. При получении адресатом этого пакета, он (адресат) должен послать отправителю подтверждение. Вот как оно выглядит: "Брат, пакет получен!" И главное - посылать все пакеты последовательно, т.е. сначала послали пакет, затем дождались подтверждения, а потом посылаем новый пакет. Какое здесь преимущество: при получении адресатом данных, он запоминает ID принятого пакета и далее шлет подтверждение. Если же отправитель подтверждение не получил, то он шлет данные заново. И наш адресат, получив данные с сохраненным ID (или с ID, меньшим сохраненного), просто их игнорирует - он ведь все эти данные уже получил! Таким образом, если данные затерялись, то подтверждение не приходит, и отправитель шлет пакет заново. Но если данные до адресата добрались успешно, а затерялся пакет-подтверждение, то при повторной пересылке данных ничего плохого не произойдет - получатель просто проигнорирует дублирующуюся информацию (да, DEiL, ты гений, я всегда это знал :) – прим. ред.).

Трафик

Представь себе такую ситуацию: проведя ровно 17 бессонных ночей, выпив 12 литров яблочного сока, ты все-таки дописал свою систему. Оттестировал и запустил. Рассказал о ней друзьям. И вот у тебя, наконец, появились долгожданные пользователи. Они радостно общались, перекидывались файлами. Затем они рассказали своим друзьям, те - своим и т.д. И вот, через пару месяцев, ты счастлив - 1000 пользователей одновременно в онлайне! А теперь посмотрим на это с другой стороны. У тебя есть 1000 пользователей. Каждые пару минут они пингуют сервер. Обмениваются сообщениями. Пересылают друг другу файлы. А трафик-то идет! И вот твой сервис закрывают, юзеры разочаровываются и уходят… И, естественно, в твоей голове зарождается вопрос - почему? А я отвечу!

Содержание  Вперед на стр. 062-118-2