Die Entstehung von verteilten COM (im Folgenden als DCOM bezeichnet) bietet uns die Möglichkeit, verteilte Anwendungen problemlos zu erstellen. Anwendungen, Entwickler können MS-RPC fast ignorieren) und leistungsstarke Funktionen und niedrige Kopplung entwickeln (Funktionsmodule sind relativ unabhängig, Es hat die Ideen von OO gut genutzt) und ist einfach zu verteiltem Computersystem bereitzustellen.
In diesem Artikel beabsichtigen wir, DCOM zu verwenden, um einen LAN -Chatraum zu entwickeln, nicht nur als technische Forschung, sondern ich glaube, dies sollte auch ein nützliches Instrument sein. Zunächst müssen wir ein allgemeines Verständnis der Funktionen dieses Chatraums haben:
1. Zumindest sollte dieser Chatraum mehreren LAN -Benutzern das Chatten ermöglichen.
2. Es sollten Unter-Chat-Räume mit mehreren Themen geben, und Benutzer können einen Chatraum zum Chat eingeben.
3. Der Client sollte so einfach wie möglich sein (ohne DCOM zu konfigurieren), und eine Serverseite muss alle Interaktionsverhaltensweisen verwalten, die Anzahl der Chatrooms und verwandten Konfigurationen verwalten und einen guten Job bei der Systemüberwachung und -protokollierung erledigen.
4. Erweitern Sie die Chatroom -Funktionen (z. B. ruhige Konversationsfunktionen, Emojis usw.). Basierend auf der obigen Funktionsbeschreibung haben wir nach sorgfältiger Analyse des Problems die folgende Skizze entwickelt:
In diesem Artikel möchten wir einen grundlegenden Kern dieses Programms grob implementieren, einschließlich Ichatmanager, Tchatroommanager und Tchatroom, um den Server mit den grundlegendsten Funktionen zu vervollständigen und eine einfache Kundenerkennung durchzuführen. Unser Fokus liegt auf der Serverseite, da die meisten Funktionen des Chatraums implementiert werden und der Kunde nur ein sehr kleines und einfaches Programm ist.
Aufgrund des Platzes listen wir den Code nur für wichtige Teile auf. Schauen wir uns zunächst an, wie unsere Ichatmanager -Oberfläche aussieht:
IChatmanager = Schnittstelle (idispatch)
['{E7CD7F0D-447F-497A-8C7B-1D80E748B67F}']
Verfahren Speakto (const Inhalt: Witestring; Destid: Integer);
// Der Kunde spricht mit dem ausgewiesenen Raum, und das Ziel ist die Zimmernummer
Funktion ReadFrom (SourceId: Integer): Isstrings;
// Der Kunde liest die Konversationsinhalte aus dem ausgewiesenen Raum, die Quell -ID ist die Zimmernummer
Funktion ReadReady (ID: Integer): Byte;
// Der Kunde kann überprüfen, ob der angegebene Raum den Gesprächsinhalt bereits lesen kann
Verfahrensbein (const Benutzername: Widestring; RoomId: Integer);
// Kundendienstmotiven in bestimmten Räumen anmelden
Verfahrensdiskutieren (const -Benutzername: Widestring; RoomId: Ganzzahl);
// Der Kunde verlässt den ausgewiesenen Raum
Funktion testclearBuffertag (RoomId: Ganzzahl): Ganzzahl;
// Kunde testet, ob die Pufferzone des angegebenen Raums gelöscht wird oder nicht
Ende;
Schauen wir uns den Abschnitt TchatManager der Schnittstellen -Implementierungsklasse an:
Typ
Tchatmanager = class (tautoObject, iChatmanager)
geschützt
Funktion ReadFrom (SourceId: Integer): Isstrings;
// Hier verwenden wir die von Delphi erweiterten komplexen Tstings, um dies zu unterstützen
// Typ, Delphi bietet eine Isstrings -Schnittstelle zur Verfügung
Verfahren Speakto (const Inhalt: Witestring; Destid: Integer);
Funktion ReadReady (ID: Integer): Byte;
// wird verwendet, um dem Kunden zu fragen, ob der angegebene Raum lesbar ist und ob der angegebene Raumpuffer leer ist
Verfahrensbein (const Benutzername: Witestring; RoomId: Integer);
SafeCall;
Prozedur Disconnectroom (const -Benutzername: Widestring; RobeId: Ganzzahl);
SafeCall;
Funktion testclearBuffertag (RoomId: Ganzzahl): Ganzzahl;
Ende;
Implementierungsteil:
var
TemProom: Tchatroom;
Beginnen
TEMPROOM: = CHATROOMMANAGER.FINDROOMBYID (socusId);
während temproom.locked tun
Beginnen
// Nichts wartet nur darauf, freigeschaltet zu werden
Ende;
GetOlestrings (temProom.oneread, Ergebnis);
Ende;
Prozedur tchatmanager.speakto (const Inhalt: Widestring; Destid: Integer);
var
TemProom: Tchatroom;
Beginnen
TemProom: = chatroommanager.findroomById (destid);
während temproom.locked tun
Beginnen
// Nichts wartet nur darauf, freigeschaltet zu werden
Ende;
TemProom.onespeak (Inhalt);
Ende;
Funktion tchatmanager.readready (ID: Ganzzahl): Byte;
var
TemProom: Tchatroom;
Beginnen
TEMPROOM: = CHATROOMMANAGER.FINDROOMBYID (ID);
Wenn temProom.canread dann Ergebnis: = 1 sonst Ergebnisse: = 0;
Ende;
Verfahren tchatmanager.Connectroom (const Benutzername: Widestring;
RobeId: Ganzzahl);
// Der Client meldet sich über die Schnittstelle in den angegebenen Raum an und ist nicht vollständig implementiert
var
TemProom: Tchatroom;
Beginnen
TemProom: = chatroommanager.findroomById (RoomId);
TemProom.loginroom (Benutzername);
Ende;
Verfahren tchatmanager
RobeId: Ganzzahl);
// Der Client verlässt den angegebenen Raum über die Schnittstelle und ist nicht vollständig implementiert
var
TemProom: Tchatroom;
Beginnen
TemProom: = chatroommanager.findroomById (RoomId);
TemProom.leaveroom (Benutzername);
Ende;
Funktion tchatManager.TestClearBufferTag (RoomId: Integer): Ganzzahl;
var
TemProom: Tchatroom;
Beginnen
TemProom: = chatroommanager.findroomById (RoomId);
Ergebnis: = temProom.clearBuffenTag;
Ende;
Initialisierung
TautoObjectFactory.create (Comserver, Tchatmanager, Class_chatmanager,
Cimultiinstance, tmapartment);
Ende.
Der wichtigste Tchatroom sieht aus wie:
Typ
Tchatroom = Klasse
Privat
FBuffer: Array [1..20] von String;
FBufferLength: Ganzzahl;
FROMNAME: String;
FROOMID: Ganzzahl;
Flocked: Boolean; // Synchronen Schloss, verwendet die Situation, in der mehrere Personen gleichzeitig Gespräche senden
FconnectCount: Ganzzahl; // die aktuelle Anzahl der Personen im Raum
FcLearBuffertag: Ganzzahl;
// Dieser Wert springt einmal jedes Mal, wenn der Puffer gelöscht wird, und dieser Puls wird vom Client erkannt
geschützt
Verfahren ClearBuffer; // den Puffer löschen
Funktion getCanread: boolean;
öffentlich
Konstruktor erstellen (Raumname: String; RoomId: Integer);
Procedure OneSpeak (Inhalt: String); // Fügen Sie dem Puffer einen Chat -Inhalt hinzu
Procedure Loginroom (Benutzername: String); // Siehe Implementierungsteil der Kommentare
PROCEDURE Leaveroom (Benutzername: String); // Beziehen Sie sich auf den Implementierungsteil der Kommentare
Funktion ONEREAD: TStrings; // Lesen Sie den Datensatz aus dem Puffer
Eigenschaft gesperrt: Boolean Read Flocked;
Eigenschaft Canread: Boolean Read GetCanread; // Bestimmen Sie, ob der Puffer leer ist, ansonsten ist er unlesbar
Eigenschaft ClearBuffertag: Ganzzahl lesen fcLearBuffenTag;
Ende;
Tchatroom -Implementierung:
{Tchatroom}
Konstruktor tchatroom.create (Raumname: String; Roomid: Integer);
Beginnen
FBufferLength: = 0;
FConnectCount: = 0;
FcLearBufferTag: = 1;
Strömt: = falsch;
FROMNAME: = Raumname;
FROOMID: = ROOMID;
Ende;
Verfahren tchatroom.ClearBuffer;
var
I: Ganzzahl;
Beginnen
/// Hier können Sie ein Flag erkennen, um festzustellen, ob der Server jeden Chat -Inhalt aufzeichnen muss.
für i: = 1 bis 20 tun
FBuffer [i]: = '';
FBufferLength: = 0;
FcLearBufferTag: = 0-FcLearBufferTag;
Ende;
Verfahren tchatroom.onespeak (Inhalt: String);
Beginnen
Verräter: = wahr;
Inc (fBufferLength);
Wenn fbufferLength> 20 dann
Beginnen
ClearBuffer;
Inc (fBufferLength);
Ende;
FBuffer [fBufferLength]: = Inhalt;
Strömt: = falsch;
Ende;
Funktion tchatroom.oneread: tstrings;
var
FSTRINGS: TStrings;
I: Ganzzahl;
Beginnen
Verräter: = wahr;
FStrings: = tstringlist.create;
für i: = 1 bis fbufferLength tun
FStrings.add (fBuffer [i]);
Ergebnis: = fStrings;
Strömt: = falsch;
Ende;
Funktion tchatroom.getCanread: boolean;
Beginnen
Ergebnis: = falsch;
Wenn fBufferLength> 0 dann Ergebnis: = True;
Ende;
Verfahren tchatroom.loginroom (Benutzername: String);
// Das Ereignis des Benutzeranmeldungsraums ist hier nicht vollständig implementiert
Beginnen
Inc (FConnectCount);
Ende;
Verfahren tchatroom.leaveroom (Benutzername: String);
// Der Benutzer verlässt das Chatroom -Ereignis, es ist hier nicht vollständig implementiert
Beginnen
Dec (fconnectCount);
Ende;
Der letzte wichtige Teil der Serverseite tchatroomManager:
Typ
Tchatroommanager = Klasse
Privat
Chatroom: Array von Tchatroom;
öffentlich
Konstruktor erstellen;
Funktion findroomById (ID: Ganzzahl): tchatroom;
Ende;
Implementierungsteil:
{Tchatroommanager}
Konstruktor tchatroommanager.create;
var
Ich, Mitbewohner: Ganzzahl;
Roomnamen: TStrings; // Roomname ist der Namen des Chatraums in der Konfigurationsdatei
Beginnen
Mitbewohner: = 1;
// Hier lesen wir mehrere Chatrooms aus der Konfigurationsdatei vor.
Raumnamen: = tstringlist.create;
Roomnames.add ('Testroom'); // Dieser Satz wird durch die endgültige Lektüre aus der Konfigurationsdatei ersetzt.
SetLength (Chatroom, Roomcount);
für i: = 1 bis Mitbewohner tun
Chatroom [i]: = tchatroom.create (Raumnamen [i-1], i);
Ende;
Funktion tchatroomManager.FindroomById (ID: Ganzzahl): tchatroom;
// Diese Funktion wird von der Ichatmanager -Schnittstelle aufgerufen, da die endgültige Version der Schnittstelle dem Kunden zur Verfügung gestellt wird
// Die Funktion, die Raumliste zu erhalten
Beginnen
Ergebnis: = Chatroom [ID];
Ende;
Initialisierung
ChatroomManager: = tchatroommanager.create;
Ende.
Nach Abschluss des Hauptkernteils der Serverkonfiguration konfigurieren wir die serverseitige DCOM-Konfiguration und können einen einfachen Client zum Testen entwickeln: (Obwohl der Client so einfach wie möglich ist, müssen wir DCOM nicht konfigurieren, aber wir immer noch Müssen Sie den serverseitigen Typ kopieren. Die Bibliotheksdatei .TLB kann erst nach der Registrierung des Clients entwickelt und verwendet werden.
Auf dem Kunden listen wir nur zwei relativ wichtige Funktionen auf, und der Rest wird weggelassen.
procedure tform1.button1click (Absender: tobject);
// klicken
Beginnen
Server.speakto (edit1.text, 1);
Ende;
procedure tform1.timer1timer (Absender: tobject);
// fordere den Konversationsinhalt von Zeit zu Zeit vom Server an und ich setze ihn auf 1,5 Sekunden ein
var
Tempstrings: TStrings;
I: Ganzzahl;
Beginnen
Wenn server.readready (1) = 1 dann
Beginnen
Tempstrings: = tstringlist.create;
SetOlestrings (tempstrings, server.readfrom (1));
Wenn freadstartpos> 19 dann
if (fcLearBufftag = 0-server.TestClearBufferTag (1)) dann
Beginnen
FreeDStartPos: = 0;
FcLearBufferTag: = server.TestClearBufferTag (1);
Ende;
für i: = freeadStartpos zu tempstrings.count-1 tun
Memo1.lines.add (tempstrings [i]);
FreeadStartpos: = tempstrings.count;
Ende;
Ende;
Der Kernteil eines DCOM-basierten LAN-Chatraums wurde im Grunde genommen abgeschlossen, und alle Tests waren relativ reibungslos. Auch es gibt eine gewisse Synchronisationsverarbeitung, aber Deadlocks oder andere Live -Schlösser treten weiter auf, wenn es viele Kunden gibt.