Появление распределенного COM (далее называемое DCOM) дает нам возможность легко создавать распределенные приложения; Приложения, разработчики могут практически игнорировать MS-RPC) и разработать мощные функции и низкую связь (функциональные модули относительно независимы. Он хорошо использовал идеи OO) и легко развернуть распределенную вычислительную систему.
В этой статье мы намерены использовать DCOM для разработки чат -комнаты LAN, не только в качестве технических исследований, но и на самом деле я считаю, что это также должно быть полезным инструментом. Прежде всего, нам нужно иметь общее понимание функций этой чаты:
1. По крайней мере, эта чата должна позволить нескольким пользователям локальной сети общаться.
2. Должны быть комнаты в подборе с несколькими темами, и пользователи могут ввести в чат в чате.
3. Клиент должен быть максимально простым (без настройки DCOM), а стороне сервера нуждается в управлении всеми поведением взаимодействия, управлению количеством чат -комнат и связанных с ними конфигураций и выполнению хорошей работы в мониторинге и ведении журнала системы.
4. Разверните функции чата (например, тихие функции разговора, смайлики и т. Д.). На основании приведенного выше функционального описания, после тщательного анализа проблемы, мы разработали следующий эскиз:
В этой статье мы хотим примерно реализовать основное ядро этой программы, включая Ichatmanager, Tchatroommanager и Tchatroom, чтобы завершить сервер с помощью самых основных функций и выполнения простого обнаружения клиента. Наше внимание сосредоточено на стороне сервера, потому что он будет реализовать большинство функций чата, а клиент - очень маленькая и простая программа.
Из -за пространства мы перечисляем только код для важных частей. Во -первых, давайте посмотрим, как выглядит наш интерфейс iChatmanager:
Ichatmanager = интерфейс (idispatch)
['{E7cd7f0d-447f-497a-8c7b-1d80e748b67f}']
Процедура Speakto (Const Content: VideString; Destid: Integer);
// клиент говорит с назначенной комнатой, а Destid - номер комнаты
Функция чтения от (SourceId: Integer): Istrings;
// Клиент читает контент разговора из назначенной комнаты, источник - номер комнаты.
функция readready (id: целое число): byte;
// клиент может проверить, может ли указанная комната уже прочитать контент разговора
Процедура Connectroom (const username: widestring; oomid: целое число);
// клиенты входят в специальные комнаты
Процедура Disconeryection (const username: widestring; oomid: целое число);
// клиент выходит из назначенной комнаты
Function TestClearBuffertag (Roomid: Integer): целое число;
// клиент проверяет, очищается ли буферная зона указанной комнаты или нет
конец;
Давайте посмотрим на раздел Tchatmanager класса реализации интерфейса:
тип
Tchatmanager = class (tautoobject, ichatmanager)
защищен
Функция чтения от (SourceId: Integer): Istrings;
// Здесь мы используем сложный тип TSTINGS, расширенные Delphi, чтобы сделать это поддержать это
// Тип, Delphi обеспечивает интерфейс Isstrings
Процедура Speakto (Const Content: VideString; Destid: Integer);
функция readready (id: целое число): byte;
// используется, чтобы предоставить клиенту запросить, является ли указанная комната читабель, и пустым указанный буфер комнаты
Процедура Connectroom (const username: widestring; oomid: целое число);
SafeCall;
Процедура Disconnecteroom (const username: widestring; oomid: целое число);
SafeCall;
Function TestClearBuffertag (Roomid: Integer): целое число;
конец;
Часть реализации:
вар
Temproom: Tchatroom;
Начинать
Temproom: = CHATRoommanager.findroombyid (SourceId);
Пока Temproom.locked Do
Начинать
// ничего не делать
конец;
GetoLestrings (temproom.oneread, результат);
конец;
Процедура tchatmanager.speakto (const content: wideString; destid: Integer);
вар
Temproom: Tchatroom;
Начинать
Temproom: = catroommanager.findroombyid (destid);
Пока Temproom.locked Do
Начинать
// ничего не делать
конец;
Temproom.onespeak (content);
конец;
function tchatmanager.readready (id: Integer): byte;
вар
Temproom: Tchatroom;
Начинать
Temproom: = Cathroommanager.findroombyid (id);
Если temproom.canread, то результат: = 1 иначе результаты: = 0;
конец;
Процедура tchatmanager.concectertoom (const username: widestring;
Комната: целое число);
// клиент входит в указанную комнату через интерфейс и не полностью реализован
вар
Temproom: Tchatroom;
Начинать
Temproom: = catroommanager.findroombyid (roomid);
Temproom.loginroom (имя пользователя);
конец;
Процедура tchatmanager.discongnectertoom (const username: widestring;
Комната: целое число);
// клиент оставляет указанную комнату через интерфейс и не полностью реализован
вар
Temproom: Tchatroom;
Начинать
Temproom: = catroommanager.findroombyid (roomid);
Temproom.leaveroom (имя пользователя);
конец;
function tchatmanager.testclearbuffertag (roomid: целое число): целое число;
вар
Temproom: Tchatroom;
Начинать
Temproom: = catroommanager.findroombyid (roomid);
Результат: = TemProom.ClearBuffertag;
конец;
Инициализация
Tautoobjectfactory.create (comserver, tchatmanager, class_chatmanager,
cimultiinstance, tmapartment);
конец.
Самый важный чат выглядит как:
тип
Tchatroom = класс
Частный
Fbuffer: массив [1..20] из строки;
Fbufferlength: целое число;
FroomName: String;
Froomid: целое число;
Столден: Boolean; // Синхронная блокировка, используется для обработки ситуации, когда несколько человек отправляют разговоры одновременно
FconnectCount: Integer; // текущее количество людей в комнате
Fclearbuffertag: целое число;
// Это значение будет прыгать один раз в каждую раз, когда буфер очищается, и этот импульс обнаруживается клиентом
защищен
Процедура ClearBuffer; // очистить буфер
Функция GetCanread: Boolean;
публичный
Конструктор Create (RoomName: String; roomid: Integer);
Процедура OneSpeak (Content: String); // Добавить контент чата в буфер
Процедура входа в систему (имя пользователя: строка); // см. В реализации часть комментариев
Процедура Leaveroom (имя пользователя: String); // См. Часть реализации комментариев
Функция OneRead: tStrings; // Читать запись из буфера
Собственность заблокирована: логическое чтение стекается;
Свойство CanRead: Boolean Read GetCanread; // Определите, является ли буфер пуст, иначе он не читается
Property ClearBuffertag: Integer Read Fclearbuffertag;
конец;
Реализация Tchatroom:
{Tchatroom}
конструктор chatroom.create (roomname: string; roomid: целое число);
Начинать
Fbufferlength: = 0;
FconnectCount: = 0;
Fclearbuffertag: = 1;
Столдно: = ложь;
FroomName: = RoomName;
Froomid: = roomid;
конец;
Процедура tchatroom.clearbuffer;
вар
я: целое число;
Начинать
/// Здесь вы можете обнаружить флаг, чтобы определить, должен ли сервер записать каждое содержание чата.
для i: = 1-20 сделать
Fbuffer [i]: = '';
Fbufferlength: = 0;
Fclearbuffertag: = 0-fclearbuffertag;
конец;
Процедура tchatroom.onespeak (Контент: строка);
Начинать
Столдно: = true;
Inc (fbufferlength);
Если fbufferlength> 20, тогда
Начинать
ClearBuffer;
Inc (fbufferlength);
конец;
Fbuffer [fbufferlength]: = content;
Столдно: = ложь;
конец;
функция tchatroom.oneread: tstrings;
вар
Fstrings: Tstrings;
я: целое число;
Начинать
Столдно: = true;
Fstrings: = tstringlist.create;
для i: = 1 до fbufferlength do
Fstrings.add (fbuffer [i]);
Результат: = fstrings;
Столдно: = ложь;
конец;
function tchatroom.getCanread: Boolean;
Начинать
результат: = false;
Если fbufferlength> 0, то результат: = true;
конец;
Процедура tchatroom.loginroom (имя пользователя: строка);
// Событие чата пользователя не полностью реализовано здесь
Начинать
Inc (fconnectCount);
конец;
Процедура tchatroom.leaveroom (имя пользователя: строка);
// пользователь покидает событие чата, оно не полностью реализовано здесь
Начинать
Dec (fconnectcount);
конец;
Последняя важная часть серверной стороны tchatroommanager:
тип
Tchatroommanager = класс
Частный
Чат: массив чата;
публичный
конструктор создать;
Function FindroomById (ID: Integer): Tchatroom;
конец;
Часть реализации:
{Tchatroommanager}
конструктор tchatroommanager.create;
вар
I, Roomcount: Integer;
RoomNames: TStrings; // RoomName - это имя чата в файле конфигурации
Начинать
Roomcount: = 1;
// Здесь мы прочитаем несколько чатов из файла конфигурации.
RoomNames: = tStringList.Create;
Poomnames.add ('testroom'); // Это предложение будет заменено окончательным чтением из файла конфигурации.
SetLength (чат, комната);
для i: = 1 к комнате
Чат [i]: = tchatroom.create (RoomNames [i-1], i);
конец;
function tchatroommanager.findroombyid (id: Integer): chatroom;
// Эта функция вызывается интерфейсом iChatmanager, поскольку окончательная версия интерфейса будет предоставлена клиенту
// Функция получения списка комнаты заключается в том, что клиент знает идентификатор своей комнаты
Начинать
Результат: = чат [id];
конец;
Инициализация
Cathroommanager: = tchatroommanager.create;
конец.
После завершения основной части серверной части сервера мы настраиваем конфигурацию DCOM на стороне сервера и можем разработать простой клиент для тестирования: (хотя клиент максимально прост, нам не нужно настроить DCOM, но мы все еще Необходимо скопировать на стороне сервера.
В клиенте мы перечисляем только две относительно важные функции, а остальные опущены.
Процедура tform1.button1click (отправитель: tobject);
// Нажмите кнопку1 и «Скажи». Содержание редактирования
Начинать
Server.speakto (edit1.text, 1);
конец;
Процедура tform1.timer1timer (отправитель: tobject);
// время от времени запрашивать контент разговора с сервера, и я установил его на 1,5 секунды
вар
Tempstrings: Tstrings;
я: целое число;
Начинать
Если Server.ReadReady (1) = 1 тогда
Начинать
Tempstrings: = tstringlist.create;
SetOleStrings (TempStrings, Server.readfrom (1));
Если FreadStartpos> 19 тогда
if (fclearbuffertag = 0-server.testclearbuffertag (1))
Начинать
FreadStartpos: = 0;
Fclearbuffertag: = server.testclearbuffertag (1);
конец;
для i: = freadstartpos to tempstrings.count-1 do
Memo1.lines.add (Tempstrings [i]);
FreadStartpos: = Tempstrings.count;
конец;
конец;
Основная часть чата на основе DCOM была в основном завершена, и все тесты были относительно плавно здесь, мне нужно добавить сложность сервера чата: разработчик должен справиться с синхронизацией. Также сделано.