La aparición de COM distribuido (en adelante, como DCOM) nos brinda la oportunidad de crear fácilmente aplicaciones distribuidas; Aplicaciones, los desarrolladores casi pueden ignorar MS-RPC) y desarrollar funciones potentes y bajo acoplamiento (los módulos funcionales son relativamente independientes, Ha hecho un buen uso de las ideas de OO) y es fácil de implementar el sistema informático distribuido.
En este artículo, tenemos la intención de usar DCOM para desarrollar una sala de chat LAN, no solo como una investigación técnica, sino que en realidad creo que esta también debería ser una herramienta útil. En primer lugar, necesitamos tener una comprensión general de las funciones de esta sala de chat:
1. Al menos esta sala de chat debería permitir que varios usuarios de LAN chaten.
2. Debe haber salas de subcat con múltiples temas, y los usuarios pueden optar por ingresar a una sala de chat para chatear.
3. El cliente debe ser lo más simple posible (sin configurar DCOM), y un lado del servidor necesita administrar todos los comportamientos de interacción, administrar la cantidad de salas de chat y configuraciones relacionadas, y hacer un buen trabajo en el monitoreo y registro del sistema.
4. Expanda las funciones de la sala de chat (como funciones de conversación tranquila, emojis, etc.). Según la descripción funcional anterior, después de analizar cuidadosamente el problema, diseñamos el siguiente boceto:
En este artículo, queremos implementar aproximadamente un núcleo básico de este programa, incluidos Ichatmanager, TchatroomManager y Tchatroom, para completar el servidor con las funciones más básicas y realizar una detección de cliente simple. Nuestro enfoque está en el lado del servidor, ya que implementará la mayoría de las funciones de la sala de chat, y el cliente es solo un programa muy pequeño y simple.
Debido al espacio, solo enumeramos el código para piezas importantes. Primero, echemos un vistazo a cómo se ve nuestra interfaz Ichatmanager:
IChatManager = interfaz (idsispatch)
['{E7CD7F0D-447F-497A-8C7B-1D80E748B67F}']
Procedimiento Speakto (Const Content: WideString; Destid: Integer);
// El cliente habla con la habitación designada, y el Destid es el número de habitación
función readFrom (SourceId: Integer): ISTRINGS;
// El cliente lee el contenido de conversación de la habitación designada, el SourceID es el número de habitación
function readready (id: integer): byte;
// El cliente puede verificar si la habitación especificada ya puede leer el contenido de la conversación
Procedimiento Connectroom (constante de usuario: wideString; roomid: entero);
// registros de clientes en habitaciones designadas
procedimiento de disconnectroom (constante nombre de usuario: widestring; habitante: entero);
// El cliente sale de la habitación designada
función testClearBuffertag (RoomId: Integer): Integer;
// El cliente prueba si la zona de búfer de la habitación especificada está borra o no
fin;
Echemos un vistazo a la sección TchatManager de la clase de implementación de la interfaz:
tipo
Tchatmanager = class (TautoObject, iChatmanager)
protegido
función readFrom (SourceId: Integer): ISTRINGS;
// Aquí usamos el tipo complejo de Tstings extendidas por Delphi, para hacer que COM admite esto
// escribe, Delphi proporciona interfaz ISTRINGS
Procedimiento Speakto (Const Content: WideString; Destid: Integer);
function readready (id: integer): byte;
// se usa para proporcionar al cliente para consultar si la habitación especificada es legible y si el búfer de habitación especificado está vacío
Procedimiento Connectroom (constante de usuario: wideString; ROOMID: entero);
SafeCall;
Procedimiento Disconnectroom (constante de usuario: wideString; RoombId: Integer);
SafeCall;
función testClearBuffertag (RoomId: Integer): Integer;
fin;
Parte de implementación:
varilla
Temproom: Tchatroom;
Comenzar
TemProom: = ChatroomManager.FindroomById (SourceId);
mientras que Temproom.
Comenzar
// No hacer nada está esperando ser desbloqueado
fin;
Getolestrings (Temproom.OnERead, resultado);
fin;
procedimiento tchatmanager.speakto (const contenido: wideString; destid: integer);
varilla
Temproom: Tchatroom;
Comenzar
TemProom: = chatroomManager.findroomByid (Destid);
mientras que Temproom.
Comenzar
// No hacer nada está esperando ser desbloqueado
fin;
TemProom.onespeak (contenido);
fin;
función tchatmanager.readready (id: integer): byte;
varilla
Temproom: Tchatroom;
Comenzar
TemProom: = chatroomManager.findroomById (id);
Si Temproom.Canread, entonces resultado: = 1 más resultados: = 0;
fin;
procedimiento tchatmanager.connectroom (constante de usuario: wideString;
ROOMID: entero);
// El cliente inicia sesión en la habitación especificada a través de la interfaz, y no está completamente implementado
varilla
Temproom: Tchatroom;
Comenzar
TemProom: = ChatroomManager.findroomByid (RoomID);
TemProom.loginroom (nombre de usuario);
fin;
procedimiento tchatmanager.disconnectroom (constante de usuario: wideString;
ROOMID: entero);
// El cliente sale de la habitación especificada a través de la interfaz y no está completamente implementado
varilla
Temproom: Tchatroom;
Comenzar
TemProom: = ChatroomManager.findroomByid (RoomID);
TEMPROOM.LEAVEROOM (nombre de usuario);
fin;
función tchatmanager.testClearBufferTag (RoomId: Integer): Integer;
varilla
Temproom: Tchatroom;
Comenzar
TemProom: = ChatroomManager.findroomByid (RoomID);
Resultado: = Temproom.ClearBuffertag;
fin;
Inicialización
TautoObjectFactory.Create (comserver, tchatmanager, class_chatmanager,
cimultiinstance, tmapartment);
fin.
El tchatroom más importante se parece:
tipo
Tchatroom = clase
Privado
Fbuffer: matriz [1..20] de cadena;
FbufferLength: Integer;
FroomName: String;
Froomid: entero;
Flocked: boolean; // bloqueo sincrónico, solía manejar la situación en la que varias personas envían conversaciones al mismo tiempo
FconnectCount: integer; // El número actual de personas en la habitación
FclearBuffertag: entero;
// Este valor saltará una vez cada vez que se borre el búfer, y el cliente detecta este pulso
protegido
procedimiento ClearBuffer; // Borrar el búfer
función getCanread: boolean;
público
constructor create (roomname: string; roomid: integer);
Procedimiento OneSpeak (contenido: cadena); // Agregar un contenido de chat al búfer
Procedimiento Loginroom (nombre de usuario: cadena); // Consulte la parte de implementación de los comentarios
Procedimiento Leaveroom (nombre de usuario: cadena); // Consulte la parte de implementación de los comentarios
Función OneRead: tstrings; // Lea el registro del búfer
Propiedad bloqueada: Boolean Read Flocked;
Propiedad Canread: Boolean Read getCanRead; // Determinar si el búfer está vacío, de lo contrario es ilegible
Propiedad ClearBuffertag: Integer Leer fclearBuffertag;
fin;
Implementación de Tchatroom:
{Tchatroom}
constructor tchatroom.create (RoomName: String; RoomId: Integer);
Comenzar
FbufferLength: = 0;
FconnectCount: = 0;
FclearBuffertag: = 1;
Flocked: = falso;
FROMNAME: = ROOMNAME;
FROMID: = ROOMID;
fin;
procedimiento tchatroom.clearbuffer;
varilla
I: entero;
Comenzar
/// Aquí puede detectar un indicador para determinar si el servidor necesita grabar cada contenido de chat.
para i: = 1 a 20 hacer
Fbuffer [i]: = '';
FbufferLength: = 0;
FcLearBuffertag: = 0-fClarBuffertag;
fin;
procedimiento tchatroom.onespeak (contenido: cadena);
Comenzar
Flocked: = verdadero;
Inc (fbufferLength);
Si fbufferLength> 20 entonces
Comenzar
ClearBuffer;
Inc (fbufferLength);
fin;
Fbuffer [fbufferLength]: = content;
Flocked: = falso;
fin;
función tchatroom.OnERead: tstrings;
varilla
Fstrings: tstrings;
I: entero;
Comenzar
Flocked: = verdadero;
Fstrings: = tStringList.create;
para i: = 1 a fbufferLength do
Fstrings.add (fbuffer [i]);
resultado: = fstrings;
Flocked: = falso;
fin;
función tchatroom.getCanread: boolean;
Comenzar
resultado: = falso;
Si fbufferLength> 0 entonces resultado: = true;
fin;
procedimiento tchatroom.loginroom (nombre de usuario: cadena);
// El evento de la sala de chat de inicio de sesión del usuario no se implementa completamente aquí
Comenzar
Inc (fConnectCount);
fin;
procedimiento tchatroom.leaveroom (nombre de usuario: cadena);
// El usuario deja el evento de la sala de chat, no se implementa completamente aquí
Comenzar
Dec (fconnectCount);
fin;
La última parte importante del lado del servidor TchatroomManager:
tipo
TchatroomManager = clase
Privado
Sala de chat: variedad de tchatroom;
público
constructor crear;
función findroomById (id: entero): tchatroom;
fin;
Parte de implementación:
{TchatroomManager}
constructor tchatroommanager.create;
varilla
I, RoomCount: entero;
Roomnames: tstrings; // Roomname es el nombre de la sala de chat en el archivo de configuración
Comenzar
Roomcount: = 1;
// Aquí leeremos varias salas de chat del archivo de configuración.
Roomnames: = tStringList.create;
RoomNames.Add ('Testroom'); // Esta oración será reemplazada por la lectura final del archivo de configuración.
setLength (sala de chat, cuarto de habitación);
para i: = 1 a RoomCount do
Sala de chat [i]: = tchatroom.create (Roomnames [i-1], i);
fin;
function tchatroomManager.findroomByid (id: entero): tchatroom;
// Esta función es llamada por la interfaz IChatManager, ya que la versión final de la interfaz se proporcionará al cliente
// La función de obtener la lista de habitaciones es para que el cliente conozca la identificación de su habitación
Comenzar
Resultado: = sala de chat [id];
fin;
Inicialización
ChatroomManager: = tchatroomManager.create;
fin.
Una vez que se completa la parte principal principal del lado del servidor, configuramos la configuración DCOM del lado del servidor y podemos desarrollar un cliente simple para las pruebas: (el cliente es lo más simple posible, no necesitamos configurar DCOM, pero aún así Necesita copiar el tipo de servidor. El archivo de biblioteca .TLB solo se puede desarrollar y utilizar después de registrar el cliente.
En el cliente solo enumeramos dos funciones relativamente importantes, y se omite el resto.
procedimiento tForm1.Button1Click (remitente: tobject);
// Haga clic en el botón1 y "Diga" el contenido de editar
Comenzar
Servidor.speakto (edit1.text, 1);
fin;
procedimiento tForm1.Timer1Timer (remitente: tobject);
// Solicite el contenido de conversación desde el servidor de vez en cuando, y lo configuré en 1.5 segundos
varilla
Temprtrings: tstrings;
I: entero;
Comenzar
if server.readready (1) = 1 entonces
Comenzar
TemprTrings: = tStringList.create;
Setolestrings (tempstrings, server.readfrom (1));
Si freadstartpos> 19 entonces
if (fclearbuffertag = 0-server.testclearbuffertag (1)) entonces
Comenzar
Freadstartpos: = 0;
FcLearBuffertag: = Server.TestClearBuffertag (1);
fin;
para i: = freadstartpos a tempstrings.count-1 do
Memo1.lines.add (tempstrings [i]);
FreadStartPos: = tempstrings.count;
fin;
fin;
La parte central de una sala de chat de LAN basada en DCOM se ha completado básicamente, y todas las pruebas han sido relativamente suaves. También lo hice.