Instant Messaging изнутри
Косякин Антон
Xakep, номер #060, стр. 060-090-2
Немного о передаче данных
Думаю, ты знаешь, что в интернете поверх IP чаще всего используются два протокола: TCP и UDP. Поэтому придется выбрать, какой же протокол использовать в своей системе. TCP, например, хорош тем, что он заботится о том, чтобы пакет дошел до нужного адресата. Но с другой стороны - из-за этого механизма трафик системы немного возрастает, приходится устанавливать для каждого клиента новое соединение. Для маленьких систем это не критично, а вот для больших уже довольно тухло. В этом плане хорош UDP: минимум трафика, никаких подключений. Ты просто отправляешь пакет на заданный адрес и порт, не думая ни о чем. Однако бывают ситуации, когда UDP-пакеты не доходят до адресата. За такими вещами тебе придется следить самому :(. Лично я использую UDP, и каждый раз, запуская клиента, молюсь, чтобы все прошло успешно. Пока все работает :).
Если ты решил остановить свой выбор на UDP, но в то же время хочешь позаботиться о сохранности передаваемых данных - могу предложить простенький алгоритм, который должен тебе помочь. Суть его такова: каждому пакету надо присвоить определенный ID (для простоты можно сначала взять 1, а потом каждый раз увеличивать его на единицу) и немного переписать функцию отправки данных. Вместо немедленной отправки пакета тебе придется помещать его в специальную очередь (очередь «ожидания»), и каждые полсекунды "пробегаться" по этой очереди и отправлять оттуда все пакеты, перемещая их уже в другую очередь (очередь «подтверждения»). Когда твой пакет будет получен клиентом, он должен отправить уведомление, что пакет с таким-то ID до адресата дошел. Тогда ты с чистой совестью можешь удалять его (пакет) из очереди «подтверждения». Если же в течение некоторого времени уведомления нет, значит, что-то случилось, и нужно проводить повторную отправку. Вот, в принципе, и все. Хотя это звучит довольно просто, но отлаживать все, думаю, придется многие-многие годы :).
При реализации алгоритма, ответственного за передачу данных, советую тебе поступить несколько нестандартно. Посмотри вот на этот пример:
int some_func()
{
struct _packet pck;
<..>
return send_packet(&pck);
};
Здесь, как ты видишь, функция кое-что делает, в результате чего формируется пакет, который нужно переслать. И для этого используется функция send_packet(). Для чего же нужно делать именно так? Вот смотри: захочешь ты, например, шифровать или сжимать свои пакеты. Или вообще записывать их в файл! Что тебе тогда придется сделать? Везде, где ты что-то отправляешь, нужно будет вставить дополнительный код. А в моем варианте нужно только подправить функцию send_packet() и все! Здорово, правда? Наверняка ты и так уже об этом догадался :). Так что любую программу, если есть вероятность того, что впоследствии ты будешь ее усложнять, советую тебе максимально структурировать. И тогда жизнь твоя станет намного проще, поверь!
С основами более или менее разобрались. Теперь перейдем к следующей части.
О реализации
Советую тебе в качестве языка программирования выбрать С/С++ и отказаться от специфичных для ОС функций. Т.е. по возможности использовать лишь стандартные библиотеки и придерживаться стандарта ANSI C/C++. В таком случае твою программу можно будет легко портировать под другие операционные системы. Лично я пишу все под Win32, а затем портирую под Linux. Ну не привык я еще ни к KDevelop, ни к vim :).