[Resumen] Los programadores que han escrito aplicaciones Winsock saben que escribir aplicaciones Winsock no es de ninguna manera una tarea fácil. No deben lidiar directamente con las API complejas en Winsock. Afortunadamente, Tclientsocket y Tservversocket en Delphi4 encapsulan Las API relevantes en Windows simplifican enormemente el acceso. a Winsock, lo que nos permite escribir aplicaciones Winsock muy fácilmente. Este artículo presenta cómo escribir aplicaciones Winsock usando Delphi a través de un ejemplo de lectura de la pantalla de otra computadora en la LAN.
Cualquiera que haya trabajado como administrador de red en un lugar de trabajo puede haber tenido esta experiencia. Qué molesto es ordenar a otros que operen mediante "control remoto" por teléfono. Además, soy una persona vaga y no quiero huir. Desde lo alto del edificio hasta la planta baja para asuntos triviales todos los días, ¿qué hacer? ¿Qué tal escribir un programa que lea la pantalla de otra computadora? Es mucho más intuitivo. Para comunicarse dentro de una LAN, la mejor opción es, por supuesto, utilizar Winsock. Los programadores que han escrito aplicaciones Winsock saben que escribir aplicaciones Winsock no es una tarea fácil. Afortunadamente, no debe tratar directamente con las complejas API en Winsock. y Tservversocket en Delphi4 encapsulan las API relevantes en Windows, lo que simplifica enormemente el acceso a Winsock y nos permite escribir aplicaciones Winsock muy fácilmente. Sin embargo, es mejor tener algunos conocimientos sobre Winsock. No entraré en detalles aquí. Puede encontrar algunos libros y leerlos usted mismo.
Para transmitir datos a través de la red, necesita al menos un par de Sockets, uno en el cliente y el otro en el servidor. Una vez que el cliente y el socket del servidor establecen una conexión, pueden comunicarse entre sí. La conexión establecida con Socket. se establece en Tcp/ Basado en ip, también admite ipx/spx y otros protocolos relacionados. En Delphi, Tclientsocket y Tservversocket se utilizan para controlar la conexión y comunicación entre el cliente y el servidor Socket. Cabe señalar que estos dos componentes se utilizan para administrar la conexión entre el servidor y el cliente. No son objetos Socket en sí mismos. Los objetos Socket son manipulados por TcustomwinSocket, como Tclientwinsocket, Tserverclientwinsocket y Tserverwinsocket.
1. Componente Tclientsocket:
Al agregar un Tclientsocket al formulario, la aplicación se convierte en un cliente Tcp/ip y Tclientsocket se puede usar para manipular el objeto Socket del cliente.
Para establecer una conexión con un servidor, primero especifica el servidor al que desea conectarse. Hay dos formas de especificar el servidor. Una es configurar el atributo Host para especificar el nombre de host del servidor, como http://www.inPRise.com o el nombre de la máquina en la LAN. Este método es intuitivo, pero. requiere resolución de nombre de dominio, que será un poco más lenta. Otro método es configurar el atributo Dirección para especificar la dirección IP del host, como 130.0.1.1. Los dos métodos son equivalentes, pero si se configuran tanto Host como Dirección, Delphi solo usará la propiedad Host.
Luego debe especificar el número de puerto para conectarse al servidor. Aquí hay dos formas: una es configurar el servicio para que utilice el número de puerto predeterminado y la otra es configurar directamente el número de puerto debajo de 1024. , se han asignado muchos, como FTP Los puertos son 20 y 21, el puerto SMTP es 25, el puerto del servidor WEB es 80, etc. Para evitar conflictos involuntarios, se recomienda que al programar su propia aplicación. Lo mejor es configurar el puerto en 1024 o superior. Si el servicio y el puerto se configuran al mismo tiempo, Delphi utilizará el puerto predeterminado del servicio.
Después de especificar el servidor y el número de puerto, llame al método abierto o establezca el atributo Activo en Verdadero. El Socket del cliente realizará una solicitud de conexión al Socket del servidor. Si el servidor está en estado de escucha, aceptará automáticamente la solicitud. solicitud para establecer una conexión. Cuando se conecta, se activa su evento Onconnet. Cuando necesite desconectarse, solo necesita llamar al método de cierre o establecer el atributo Activo en Falso. En este momento, se activará el evento ondisconnet.
2. Componente Tservversocket:
Al igual que Tclientsocket, para construir un servidor, solo necesita colocar un componente Tserversock en el formulario.
El objeto de socket del lado del servidor es más complicado de administrar. Cuando el servidor está en estado de escucha, Tservversocket manipula el objeto de socket del servidor; cuando el cliente realiza una solicitud, el servidor responde a la solicitud y establece una conexión. En este momento, Tserverclientwinsocket se utiliza para manipular la conexión entre el servidor. Socket y el Socket del cliente.
Para poner el servidor en estado de escucha, primero debe especificar el número de puerto. Por supuesto, debe ser el mismo que el número de puerto del cliente. Luego llame al método open o establezca la propiedad Active en True.
3. Comunicación:
Una vez que se establece la conexión entre el cliente y el servidor, puede comenzar la comunicación entre sí. Delphi proporciona varios métodos de comunicación para Tservversocket y Tclientsocket. Sendtext se usa para enviar información de texto, sendstream se usa para enviar transmisiones y SendBuf se usa para enviar datos de una longitud específica.
Cabe señalar que dado que el tamaño de búfer predeterminado de Windows es 4K, al enviar información de más de 4K, por ejemplo, una secuencia binaria enviada desde el servidor al cliente, solo necesita usar Socket.SendStream() en el servidor. , pero es diferente en el cliente. Activará el evento onread varias veces y Delphi no define eventos como "onreadend". Por lo tanto, el programador debe recopilar los datos él mismo al recibirlos. El método adoptado en este artículo es enviar primero la longitud de la secuencia al cliente y luego enviar la secuencia. El cliente escribe los datos recibidos en una secuencia. Cuando la longitud de la secuencia es igual a la longitud enviada por el servidor. que el cliente haya terminado de recibirlo. Para el servidor, la secuencia utilizada como parámetro de transmisión será "propiedad" del Socket. Cuando finalice el objeto Socket, no lo libere usted mismo; de lo contrario, se activará una excepción.
Asimismo, cuando el texto enviado es inferior a 4K, por ejemplo al realizar la siguiente llamada en el programa cliente
clientsocket1.Socket.SendText('obtiene');
clientsocket1.Socket.SendText('obtiene');
clientsocket1.Socket.SendText('obtiene');
Cuando el servidor recibe, aparecerán fenómenos como getgets. Esto puede deberse a que cuando los datos en el búfer aún no se han enviado, se coloca texto nuevo en el búfer y la computadora lo trata como el mismo lote de datos para procesar. . Para evitar que ocurra este fenómeno, puedes utilizar el método de "lanzar la pelota" de un lado a otro en el programa:
servidor cliente
clientsocket1.Socket.SendText('datos1') socket.ReceiveText;
socket.sendtext('ok');
socket.receivetext;
clientsocket1.Socket.SendText('datos2')
socket.ReceiveText;
socket.sendtext('fin');
socket.receivetext;
Después de ejecutar el programa del servidor en otra computadora, ingrese el nombre de la computadora en el cuadro de texto de su programa cliente, haga clic en "Conectar" y haga clic en "Obtener imagen". Tendrá una vista clara de la pantalla de la computadora de la otra parte. El siguiente es el código fuente completo del programa. Este programa puede ejecutarse en NT4.0, Win95, Win98 y LAN. Por supuesto, Windows debe tener instalado el protocolo TCP/IP y debe tener una IP asignada o especificada dinámicamente. DIRECCIÓN.
Si le resulta problemático "comando" mientras mira, también puede analizar los eventos del teclado y el mouse en la imagen 1 y luego enviarlos al servidor. Una vez que el servidor los reciba, realizará la misma operación nuevamente, para que usted no lo haga. No tienes que preocuparte. Operador. Con Tclientsocket y Tservversocket de Delphi, también puede completar el desarrollo de aplicaciones como copia de archivos, chat en línea, ICQ, etc. Es muy simple de implementar. Puede usar libremente su imaginación para escribir programas más atractivos.
Programa cliente:
unidad cmmain;
interfaz
usos
Windows, Mensajes, SysUtils, Clases, Gráficos, Controles, Formularios, Cuadros de diálogo,
ScktComp, StdCtrls, ExtCtrls, jpeg;
tipo
TForm1 = clase(TForm)
Panel1: Panel T;
ScrollBox1: TScrollBox;
Imagen 1: TImagen;
Botón1: TBotón;
Edición1: TEditar;
Botón2: TBotón;
ClientSocket1: TClientSocket;
Etiqueta1: TLabel;
procedimiento Button1Click(Remitente: TObject);
procedimiento Button2Click(Remitente: TObject);
procedimiento ClientSocket1Connect(Remitente: TObject;
Zócalo: TCustomWinSocket);
procedimiento ClientSocket1Error(Remitente: TObject; Socket: TCustomWinSocket;
ErrorEvent: TErrorEvent; var ErrorCode: Entero);
procedimiento ClientSocket1Read(Remitente: TObject; Socket: TCustomWinSocket);
procedimiento FormCreate(Remitente: TObject);
procedimiento FormClose(Remitente: TObject; var Acción: TCloseAction);
privado
{Declaraciones privadas}
público
{Declaraciones públicas}
fin;
var
Formulario1: TForm1;
c:inteto largo;
m:tmemorystream;
implementación
{$R *.DFM}
procedimiento TForm1.Button1Click(Remitente: TObject);
comenzar
intentar
clientesocket1.Cerrar;
clientsocket1.Host:=edit1.text;
clientsocket1.Open; //Conéctate al servidor
excepto
showmessage(edit1.text+#13#10+'La computadora no está encendida o el programa de servicio no está instalado');
fin;
fin;
procedimiento TForm1.Button2Click (Remitente: TObject);
comenzar
clientsocket1.Socket.SendText('gets'); //Enviar una solicitud para notificar al servidor que se necesita una imagen de pantalla
fin;
procedimiento TForm1.ClientSocket1Connect(Remitente: TObject;
Zócalo: TCustomWinSocket);
comenzar
caption:='Conectar a'+edit1.text;
fin;
procedimiento TForm1.ClientSocket1Error(Remitente: TObject;
Conector: TCustomWinSocket; ErrorEvent: TErrorEvent;
varErrorCode: Entero);
comenzar
caption:='Conexión'+edit1.text+'Error';
showmessage(edit1.text+#13#10+'La computadora no está encendida o el programa de servicio no está instalado');
código de error:=0;
fin;
procedimiento TForm1.ClientSocket1Read(Remitente: TObject;
Zócalo: TCustomWinSocket);
var
buffer:array [0..10000] de byte //Establece el buffer de recepción;
len:entero;
ll:cadena;
b:tmapa de bits;
j:tjpegimage;
comenzar
si c=0 entonces //C es el número de bytes enviados por el servidor. Si es 0, significa que la recepción de la imagen aún no ha comenzado.
comenzar
ll:=socket.ReceiveText;
c:=strtoint(ll); //Establece el número de bytes a recibir
clientsocket1.Socket.SendText('okok'); //Notificar al servidor para comenzar a enviar imágenes
fin de otra manera
comenzar // La siguiente es la parte de recepción de datos de la imagen
len:=socket.ReceiveLength //Leer la longitud del paquete
socket.ReceiveBuf(buffer,len); //Recibir el paquete de datos y leerlo en el buffer
m.Write(buffer,len); //Agregar a la secuencia M
if m.Size>=c entonces //Si la longitud del flujo es mayor que el número de bytes a recibir, la recepción se completa
comenzar
m.Posición:=0;
b:=tbitmap.Crear;
j:=tjpegimage.Crear;
intentar
j.LoadFromStream(m); //Leer los datos de la secuencia M en el objeto de imagen JPG J
b.Assign(j); //Convertir JPG a BMP
Image1.Picture.Bitmap.Assign(b); //Asignar al componente image1
finalmente // El siguiente es el trabajo de limpieza.
b.gratis;
j.libre;
clientsocket1.Active:=falso;
clientsocket1.Active:=verdadero;
m.Borrar;
c:=0;
fin;
fin;
fin;
fin;
procedimiento TForm1.FormCreate(Remitente: TObject);
comenzar
m:=tmemorystream.Create;
fin;
procedimiento TForm1.FormClose(Remitente: TObject; var Acción: TCloseAction);
comenzar
m.libre;
ClientSocket1.Cerrar;
fin;
fin.
Programa de servidor:
unidad principal;
interfaz
usos
Windows, Mensajes, SysUtils, Clases, Gráficos, Controles, Formularios, Cuadros de diálogo,
ScktComp,jpeg;
tipo
TForm1 = clase(TForm)
ServerSocket1: TServerSocket;
procedimiento ServerSocket1ClientRead(Remitente: TObject;
Zócalo: TCustomWinSocket);
procedimiento FormCreate(Remitente: TObject);
privado
{Declaraciones privadas}
público
{Declaraciones públicas}
fin;
var
Formulario1: TForm1;
m1:tmemorystream;
implementación
{$R *.DFM}
procedimiento TForm1.ServerSocket1ClientRead(Remitente: TObject;
Zócalo: TCustomWinSocket);
var
s,s1:cadena;
escritorio:tcanvas;
mapa de bits:tmapa de bits;
jpg:tjpegimage;
comenzar
s:=socket.ReceiveText;
if s='gets' then //El cliente emite una solicitud
comenzar
mapa de bits:=tbitmap.Create;
jpg:=tjpegimage.Crear;
desk:=tcanvas.Create; //El siguiente código es para obtener la imagen de la pantalla actual
escritorio.Handle:=getdc(hwnd_desktop);
m1:=tmemorystream.Create; //Inicializa el flujo m1, después de enviar el flujo con sendstream(m1),
//Permanecerá hasta que finalice la conversación del socket,
//No se puede liberar manualmente; de lo contrario, se activará una excepción
con mapa de bits hacer
comenzar
ancho:=pantalla.Ancho;
altura:=pantalla.Altura;
lienzo.CopyRect(canvas.cliprect,escritorio,escritorio.cliprect);
fin;
jpg.Assign(bitmap); //Convierte la imagen a formato JPG
jpg.SaveToStream(m1); //Escribe la imagen JPG en la secuencia
jpg.gratis;
m1.Posición:=0;
s1:=inttostr(m1.tamaño);
Socket.sendtext(s1); //Enviar tamaño de imagen
fin;
if s='okok' entonces //El cliente está listo para recibir imágenes
comenzar
m1.Posición:=0;
Socket.SendStream(m1); //Enviar imagen JPG
fin;
fin;
procedimiento TForm1.FormCreate(Remitente: TObject);
comenzar
ServerSocket1.abierto;
fin;
fin.