Ver Mensaje Individual
  #2  
Antiguo 01-05-2007
Avatar de seoane
[seoane] seoane is offline
Miembro Premium
 
Registrado: feb 2004
Ubicación: A Coruña, España
Posts: 3.717
Reputación: 24
seoane Va por buen camino
Una posible solución es enviar el archivo y luego desconectar, de esta forma solo tendríamos que leer, en el lado del servidor, hasta que la conexión se cierre.

Por ejemplo:
Código Delphi [-]
const
  BufferSize = 32 * 1024;

// En el evento OnAccept del TTCPServer (BlockMode = bmThreadBlocking)
procedure TfrmMain.ServidorAccept(Sender: TObject;
  ClientSocket: TCustomIpClient);
var
  Buffer: PByte;
  Recibidos: Integer;
begin
  // La primera linea que recibimos es la ruta donde guardar el archivo
  with TFileStream.Create(ClientSocket.Receiveln, fmCreate) do
  try
    // Reservamos memoria para el buffer
    GetMem(Buffer,BufferSize);
    try
      // Recibimos los datos del archivo hasta que se cierre la conexion
      Recibidos:= ClientSocket.ReceiveBuf(Buffer^,BufferSize);
      while Recibidos > 0 do
      begin
        // Guardamos los datos recibidos en el archivo
        WriteBuffer(Buffer^,Recibidos);    
        Recibidos:= ClientSocket.ReceiveBuf(Buffer^,BufferSize);
      end;
    finally
      // Liberamos la memoria
      FreeMem(Buffer);
    end;
  finally
    Free;
  end;
end;
El cliente lo implemento dentro de un thread, ya que voy a colocar la propiedad BlockMode = bmBlocking y no quiero que se me bloquee el resto de la aplicación. Aunque puede parecer complicado, esto nos permitirá mandar varios archivos a la vez y también cancelar el envió antes de que termine.

El thread cliente, que yo llamare TEnvio, lo implemento asi:
Código Delphi [-]
// Debajo de interface, junto a la definicion del formualrio
 TEnvio = class(TThread)
  private
    FCliente: TTCPClient;
    FLocalFile: String;
    FRemoteFile: String;
  protected
    procedure Execute; override;
  public
    constructor Create(LocalFile,RemoteFile,Host,Port: String);
    destructor Destroy; override;
  end;


// Debajo de implementation
{ TEnvio }

constructor TEnvio.Create(LocalFile,RemoteFile,Host,Port: String);
begin
  inherited Create(FALSE);
  // Le indicamos que se destruya al termianr
  FreeOnTerminate:= TRUE;
  FLocalFile:= LocalFile;
  FRemoteFile:= RemoteFile;
  // Creamos un TTCPClient
  FCliente:= TTCPClient.Create(nil);
  FCliente.RemoteHost:= Host;
  FCliente.RemotePort:= Port;  
  FCliente.BlockMode:= bmBlocking;
end;

destructor TEnvio.Destroy;
begin
  // Destruimos el TTCPClient
  FCliente.Free;
  inherited;
end;

procedure TEnvio.Execute;
var
  Buffer: PByte;
  Leidos: Integer;
begin
  inherited;
  // Abrimos el archivo como solo lectura
  with TFileStream.Create(FLocalFile,fmOpenRead or fmShareDenyWrite) do
  try
    // Reservamos memoria para el buffer
    GetMem(Buffer,BufferSize);
    try
      // Intentamos conectar con el servidor
      FCliente.Active:= TRUE;
      try
        // Enviamos la ruta donde se debe guardar el archivo
        FCliente.Sendln(FRemoteFile);
        // En este bucle enviamos el archivo
        Leidos:= Read(Buffer^,BufferSize);
        while (Leidos > 0) and not Terminated do
        begin
          FCliente.SendBuf(Buffer^,Leidos);
          Leidos:= Read(Buffer^,BufferSize);
        end;
      finally
        // Cerramos la conexion
        FCliente.Active:= FALSE;
      end;
    finally
      FreeMem(Buffer);
    end;
  finally
    Free;
  end;
end;

Un ejemplo de como usar lo anterior:
Código Delphi [-]
var
  Envio: TEnvio;
begin
  with TOpenDialog.Create(nil) do
  try
    if Execute then
    begin
      Envio:= TEnvio.Create(Filename, 'C:\' +  ExtractFileName(Filename),
        txtHost.Text, '2000');
    end;
  finally
    Free;
  end;
end;
En cualquier momento podemos cancelar la transmisión utilizando "Envio.Terminate". Pero te dejo a ti escoger cuando y donde utilizar esa opción. Otras mejoras pueden ser que la ruta del archivo remoto sea relativa y no absoluta, por motivos de seguridad, o enviar junto con el archivo su hash md5 para comprobar que ha llegado bien. Pero eso lo podemos dejar para mas adelante ...

Aquí te dejo el proyecto envuelto para regalo ...
Archivos Adjuntos
Tipo de Archivo: zip Ejemplo40.zip (5,6 KB, 192 visitas)
Responder Con Cita