Member
Статус: Не в сети Регистрация: 03.01.2004 Откуда: Питер
ANTIHacker
Цитата:
Кстати, кто-нибудь знает ссылку на исходник чата для локалки ? Ищу, но никак не найду.
Плохо ищешь, вот:
Код:
Чат для локалки собственными руками В этой статье тебя ожидает рассказ про UDP протокол.
ТЕОРИЯ ПРОТОКОЛА
На данный момент существует два основных и самых распространенных протокола - TCP и UDP. Раньше был еще очень распространен IPX, который использовала фирма Novell. Но на данный момент он отходит, и уже редко увидишь такого зверя. Только на старых системах можно увидеть IPX. Большинство остальных протоколов, которые ты знаешь (FTP, HTTP, POP3, SMTP и дальше в том же духе), работают поверх TCP или UDP. Что это значит - "поверх другого протокола"? В TCP реализованы основные функции для работы с сетью. Он умеет устанавливать соединение с удаленным компом, передавать и принимать данные и проверять правильность получения серваком отправленных пакетов. Теперь мы хотим создать протокол для передачи файлов (FTP). Для этого берем TCP, наделяем его нужными нам возможностями и - получите- распишитесь. Вот и получается, что FTP работает через (поверх) протокола TCP. Если бы мы захотели создать FTP с чистого листа, то нам пришлось бы заново реализовывать функции установки соединения и передачи данных. А так нам нужно только подготовить данные в спецформате (протокола FTP) и отдать их протоколу TCP, и он сам уже установит соединение и отдаст эти данные куда надо. Именно по такому принципу работает сеть. Все это дело стандартизировано, и если хочешь узнать подробнее, то почитай какую-нибудь доку про модель OSI (Open Systems Interconnection) и ее семь уровней (тут опять могу отослать на свой сайт, где я уже все подробно описал). Эта тема довольно интересна, и в любом случае желательно знать устройство протоколов.
ПРОТОКОЛ UDP
Протокол UDP очень похож на TCP. В нем также реализованы возможности передачи данных, но он не устанавливает соединения и не поддерживает целостности передаваемых данных. Протокол просто открывает порт, выплевывает туда порцию данных и даже не волнуется о том, дошли они к получателю или нет. Поэтому UDP работает намного быстрей. Если ты захочешь работать с этим протоколом, то проверку правильности получения данных придется реализовывать самому. Так что для передачи файлов или другой инфы большого размера ты должен выбрать TCP. Ну а для чата, который мы сегодня напишем, более удобным вариантом будет UDP. Он очень быстрый и при маленьких сообщениях очень эффективен. В Delphi для работы с UDP протоколом хорошо подходит библиотека Indy. Мы ее уже использовали, когда писали пример утилиты WhoIs. Сегодня снова возвращаемся к ней.
БУДЬ ГОТОВ!
Разомни пальцы, мышку, клаву и запусти Delphi. Сейчас мы приступим к моему любимому занятию.... Да нет, не к сексу. Я его тоже люблю, но сегодня мы займемся кодингом, а секс оставим на ночь :).
На форме мне понадобятся:
1. Компонент TMemo. Его можно растянуть почти по всей форме.
2. Компонент TEdit, в который мы будем писать отправляемое сообщение.
3. Кнопка TButton, по нажатию которой сообщение будет отсылаться. Для работы с портами нам нужны компоненты idUDPClient с закладки "Indy Clients" и idUDPServer с закладки "Indy Servers". Брось по одному такому компоненту на форму. Теперь нужно настроить протокол UDP. Первое что сделаем - выберем любой порт от 1 до 65 тысяч, через который будет происходить связь. Я решил выбрать 11245 (ты можешь выбрать любое другое). Установи это значение у свойства Port компонента idUDPClient и у свойства DefaultPort компонента idUDPServer. Это заставит клиента и сервера работать на одном и том же порту, а значит может осуществиться связь. ЗАПОМНИ!!! Порты протокола UDP не пересекаются с портами TCP. Это значит, что TCP порт 80 не равен UDP порту 80. Теперь у клиента (idUDPClient) нужно указать свойство Host. Сюда записывается IP адрес компа, которому будут отправляться сообщения. Но у нас чат и сообщения должны получать все пользователи в сетке, запустившие прогу. Поэтому, чтобы не было проблем, желательно установить у обоих компонентов свойство BroadcastEnabled в true. А вместо конкретного IP адреса использовать широковещательный (такой адрес, который получают все). Если у тебя в сетке используются адреса типа 192.168.100.х, то для тебя широковещательный адрес будет 192.168.100.255 (последний октет меняем на 255). Приготовления окончены, можно кодить.
ШКОДИНГ
Создай обработчик события OnClick для кнопки и напиши там следующий код:
procedure TForm1.Button1Click(Sender: TObject); begin IdUDPClient1.Send(Edit1.Text); end;
Здесь всего одна строчка, которая отправляет с помощью UDP клиента содержимое строки ввода (компонента Edit1). Теперь нужно научить UDP сервер получать эту инфу. Для этого создай обработчик события OnUDPRead для компонента IdUDPServer. В нем напиши содержимое листинга 1, а я попытаюсь доходчиво описать происходящее. У процедуры-обработчика события есть три параметра. Первый присутствует во всех обработчиках и ничего интересного для нас сегодня в себе не несет. Второй - это данные, которые получены из сети. Третий - тут хранится информация о том, откуда пришли данные. Итак, полученные данные хранятся во втором параметре. Они приходят к нам как простой неформатированный поток TStream. Чтобы удобней было работать с данными, их лучше перегнать в строковый поток TStringStream. Ты думаешь, это неудобно? Неудобно на потолке сексом заниматься, одеяло падает. А также когда соседские дети на тебя похожи. А тут все удобно. А вдруг ты передаешь не текст, а картинку, и компонент форматнет ее в текст? Вот это уже будет не неудобно, а полный облом. Смотри, как легко все превращается в текст. В обработчике я объявил одну переменную StringFormatedStream типа TStringStream (строковый поток). Первой строкой кода я его инициализирую. Во второй строчке я копирую в строковый поток данные из простого неформатированного потока. Все!!! Теперь переданный мне текст находится в свойстве DataString строкового потока StringFormatedStream. Я смело могу выводить этот результат в компонент Memo. Но мы же пишем чат, и желательно еще и выводить информацию о том, кто сказал этот текст. Для примера я вывожу IP адрес отправителя данных, который находится в свойстве PeerIP третьего параметра ABinding. Но это только для примера и в реальной ситуации это некрасиво. Поэтому ты можешь добавлять имя отправителя сразу в текст отправки. Это значит, что по нажатию кнопки отправки сообщения нужно изменить код следующим образом:
IdUDPClient1.Send('Сюда помести имя отправителя'+ Edit1.Text);
Можно дать возможность юзверю вводить имя в отдельной строке ввода Edit2. В этом случае код будет таким:
IdUDPClient1.Send(Edit2.Text+' '+Edit1.Text);
Все!!! Кодинг окончен.
COMPLETE!
Если у тебя все получилось, то можешь запустить прогу и пообщаться с самим собой. Ну а если благодаря Х ты уже осетенил свой дом, район, город (нужное подчеркнуть), то устанавливай свой чат всех сетянам и общайся. Чат простой, но очень быстрый и абсолютно не нагружает систему, в отличие от чатов на основе TCP. Если у тебя возникли проблемы с компиляцией, то Delphi (как и у меня) забыл добавить к проекту модуль idSocketHandle. Допиши его в раздел uses, и проблемы уйдут.
ЛИСТИНГ 1
procedure TForm1.IdUDPServer1UDPRead(Sender: TObject; AData: TStream; ABinding: TIdSocketHandle); var StringFormatedStream: TStringStream; s: String; begin //Инициализация StringFormatedStream := TStringStream.Create(''); //Копирование из простого потока в строковый. StringFormatedStream.CopyFrom(AData, AData.Size); //Вывод полученного сообщения Memo1.Lines.Add(ABinding.PeerIP+' '+StringFormatedStream.DataString); //Перенаправление сообщения дальше ABinding.SendTo(ABinding.PeerIP, ABinding.PeerPort, s[1], Length(s)); //Освобождение строкового потока. StringFormatedStream.Free; end;
_________________ Здесь так мало тех, с кем легко говорить,
Еще меньше тех, с кем не страшно молчать (c)
Member
Статус: Не в сети Регистрация: 03.01.2004 Откуда: Питер
ANTIHacker
Цитата:
А что за ресурс, если не секрет?
Непомню, какой-то FAQ
Цитата:
Сделал всё как написано, но выдается ошибка в строчке
Ну дак переведи, там-же по русски(вернее по английски, но не суть) написано: "несовместимые типы", смотри где в это время курсор стоит, он тебе укажет, что не нравиться Ну а дальше смотри по тексту. И надеюсь ты idSocketHandle не забыл добавить в юзез Обычно в таких исходниках специально ошибки делают, типа чтобы ламеры просто так не передирали. Мне один раз попался исходняк, где все "1" были заменены на букву "l" (L), а "о" на "0", ох я матерился! Благо в дельфе есть Replace
_________________ Здесь так мало тех, с кем легко говорить,
Еще меньше тех, с кем не страшно молчать (c)
Member
Статус: Не в сети Регистрация: 14.01.2004 Откуда: Киев, Украина
Простой вопрос: как более грамотно отцентрировать текст в TEdit, допустим в .net TTextBox - аналоге TEdit и TMemo есть такое свойство, а как быть с Delphi?
Member
Статус: Не в сети Регистрация: 30.01.2004 Откуда: from offline
Вопроса два:
1. Ктонибуть писал Звонилку ? Я скачал исходник переделал Называется поект RasDemo мож кто виел.
Так вот в XP всё нормально в 98 при повторном дозвоне выкидывает ошибку: Порт уже открыт.
есле принудительно завершить процес "rnaapp" помоему так пишется - то всё нормально. кто нибуть знакт как победить ?
2. NMFTP - компонента нужно узнать размер определённого файла - нужно чтобы гусеницу сделать(прогрес бар закачки)
можно list делать и потом из всего листа смотреть - но т.к. сервер тормозной и на него нагрузка большая тупит.
Как можно получит размер не качая весь лист ?
_________________ aka Ronin aka loop
Последний раз редактировалось 2poy 02.04.2005 14:15, всего редактировалось 1 раз.
Member
Статус: Не в сети Регистрация: 14.01.2004 Откуда: Киев, Украина
И еще возникла проблема, которую я не могу решить: есть Edit и теперь необходимо, чтобы он был недоступен для редактирования данных/выделения текста, enabled был-бы в самый раз, но шрифт становиться неактивного цвета.
Advanced member
Статус: Не в сети Регистрация: 09.06.2003 Откуда: USSR
Daemon Отключи TabStop чтобы клавишей не попадали и перекидывай на другой если всеже получил фокус.
Только зачем тебе так не понимаю? Можно же для вывода просто тескта использовать TStaticText с рамкой.
Member
Статус: Не в сети Регистрация: 14.01.2004 Откуда: Киев, Украина
Цитата:
Можно же для вывода просто тескта использовать TStaticText с рамкой.
Не эстетично как-то
Добавлено спустя 8 часов, 11 минут, 39 секунд: Вообщем всегда со своими проблемами необходимо разбираться самому. Вот как я модернизировал выше приведеный компонент:
Member
Статус: Не в сети Регистрация: 11.11.2004 Откуда: Челябинск
Zoom Evstrahiev TPanel - оконный компонент, имеет хэндл окна, жрет соб... системные ресурсы как и все от TWinControl, в отличие от производных от TGraphicControl.
Daemon Из базуки по комарам...
_________________ пишу я программу... и вдруг на клавиатуру выползает bug, буквально
Member
Статус: Не в сети Регистрация: 14.01.2004 Откуда: Киев, Украина
Rius
Цитата:
Daemon Из базуки по комарам...
Чего не зделаешь ради эстетики На самом деле ограничивающим фактором явилось использование манифеста, т.е. нужно чтобы окно имело текущую тему, даже TEdit, ну и главное - нежелание переписывать код
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 1
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения