Problema: delphi, socket y envios de archivos

Iniciado por N3Tw0lf, 14 Mayo 2011, 07:07 AM

0 Miembros y 1 Visitante están viendo este tema.

N3Tw0lf

Hola muy buenas gente este es mi primer post en el foro espero que me puedan ayudar (: .
tengo este codigo que sirve para que mi cliente socket en delphi reciba un archivo lo entiendo poco, pero igualmente funciona bien con archivos de texto. Se trata de una conexion con de socket normal que trae delphi , el servidor recibe bien archivos de texto (.txt) pero el problema lo tengo cuando quiero mandar un ejecutable, el servidor lo recibe pero vacio :s osea 0 kb  la verdad no tengo la menor idea de cual puede ser el problema alguien me podria dar una mano? en cual es el error o el problema? se lo agradeceria mucho ya que estoy estancado en mi programa por este problema :s les dejo el codigo:
Código (delphi) [Seleccionar]
procedure TForm1.ServerSocket1ClientRead(Sender: TObject;
 Socket: TCustomWinSocket);
var
 size: Integer;
 strcom, com:string;
 nreceived,i:integer;
 Stream:  TMemoryStream;
 buffer: array  [0..99999] of char;
begin
strcom:=Socket.ReceiveText;
if pos('TOMA',strcom)=1 then
 begin
       Stream := TMemoryStream.Create;
       Screen.Cursor := crHourglass;
       try
         while True do
         begin
           nReceived := Socket.ReceiveBuf (Buffer, sizeof (Buffer));
           if nReceived <= 0 then
             Break
           else
             Stream.Write (Buffer, nReceived);
           Sleep (200);
         end;
         Stream.Position := 0;
         stream.SaveToFile('C:\Prueba.txt');
       finally
         Stream.Free;
         Screen.Cursor := crDefault;
       end;
 end;

Bueno espero que alguien me pueda ayudar
gracias y saludos

Experiencia es el nombre que le damos a nuestros errores

Khronos14

Por lo que veo en tu código haces cosas poco recomendable.

Un bucle infinito sin sentido, la condición que usas para el break la puedes usar para salir del bucle. El sleep no pinta nada, y la rutina como no se ejecuta en un thread te falta un Application.ProcessMessages dentro del bucle para que no se te congele la aplicación.

Deberías poner el código del socket que envía el archivo.

Saludos.

N3Tw0lf

Hola, antes que nada muchas gracias por responder ,al fin alguien me puede dar una ayuda ;-), bueno la vdad no tengo la menor idea de como manejar esto de enviar y recibir archivos por socket el codigo lo saque de otro foro y fui trantando de entenderlo ejecutandolo varias veces y cambiandole algunas cosas. Te dejo el codigo que envia el archivo:
Código (delphi) [Seleccionar]
procedure TForm1.Button1Click(Sender: TObject);
var
strm:TMemoryStream;
begin
strm:=TMemorystream.Create;
strm.LoadFromFile('C:\Pruebaa.txt');
clientsocket1.Socket.SendText('TOMA');
clientsocket1.socket.SendStream(strm);
end;

Teniendo el archivo una extension .txt el code transporta el archivo bien sin ningun error pero cuando intento combiar la extension a .exe (un ejecutable) el archivo se crea pero vacio.

Bueno espero que me puedas ayudar
saludos.

Experiencia es el nombre que le damos a nuestros errores

Khronos14

¿Que versión de Delphi estás utilizando? Porque si tu versión de Delphi tiene UNICODE hay que hacerlo de una forma u otra, ya que las variables string, char y pchar tienen un valor distinto.

Saludos.

N3Tw0lf

Delphi 7 ,perdona por no poner todos los datos  :-\,

Saludos
Experiencia es el nombre que le damos a nuestros errores

d(-_-)b

talvez mi respuesta no resuelva tu probema, pero por si a caso...

Te recomiendo este interesante material.

Windows Socket Programming using the WinSock API

ttp://www.felix-colibri.com/papers/web/socket_programming/socket_programming.html

A mi personalmente los componentes indy nunca me han gustado.

No hay nada mejor que usar la API

aqui puedes encontrar mucho material http://www.delphibasics.info/

suerte.

saludos...
Max 400; caracteres restantes: 366

N3Tw0lf

#6
Hola , muchas gracias por interesarte, el primer enlace lo conocia y esta bueno, el segundo enlace no me sirvio de mucho, igual te lo agradezco nuevamente, concordamos en algo por lo menos jeje a mi tampoco me gustan las indy :P. hay >_< espero que alguien me pueda ayudar por que ya ase mas de una semana estoy tratando de buscar la respuesta a mi problema u.u

Espero mas respuestas por favor

Saludos.
Experiencia es el nombre que le damos a nuestros errores

Khronos14

El principal problema está en la función SendStream, que no envía archivos mayores que 8192 bytes, no se porqué. La solución es hacer un pequeño algoritmo para que lea del fichero y a la vez los mande por un socket.

Código (delphi) [Seleccionar]

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ScktComp, StdCtrls;

type
  TFMain = class(TForm)
    ClientSocket1: TClientSocket;
    ServerSocket1: TServerSocket;
    Button1: TButton;
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure ClientSocket1Read(Sender: TObject; Socket: TCustomWinSocket);
    procedure FormDestroy(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  FMain: TFMain;
  fsToReceive: TFileStream;

implementation

{$R *.dfm}

procedure TFMain.Button1Click(Sender: TObject);
var
Buff: array [0..1023] of byte;
BytesRead: integer;
fsToSend: TFileStream;
begin
  try
    fsToSend:= TFileStream.Create('C:\prueba.mp3', fmOpenRead or fmShareDenyWrite);
    fsToSend.Seek(0, 0);

    repeat
      FillChar(Buff, 1024, 0);
      BytesRead:= fsToSend.Read(Buff, 1024);
      Application.ProcessMessages;
      if BytesRead > 0 then
        ServerSocket1.Socket.Connections[0].SendBuf(Buff, SizeOf(Buff));
    until fsToSend.Position = fsToSend.Size;

  finally
    fsToSend.Free;
  end;
end;

procedure TFMain.ClientSocket1Read(Sender: TObject; Socket: TCustomWinSocket);
var
BytesRead: integer;
Buff: array [0..1023] of byte;
begin
  if Assigned(fsToReceive) = false then
    fsToReceive:= TFileStream.Create('C:\recibido.mp3', fmCreate or fmOpenReadWrite);

  FillChar(Buff, 1024, 0);
  BytesRead:= Socket.ReceiveBuf(Buff, 1024);
  fsToReceive.Write(Buff, BytesRead);
end;

procedure TFMain.FormCreate(Sender: TObject);
begin
  try
    ServerSocket1.Active:= True;
    ClientSocket1.Active:= True;
  Except on Exception do
    raise Exception.Create('Ocurrió con el servidor o con el cliente');
  end;
end;

procedure TFMain.FormDestroy(Sender: TObject);
begin
  if Assigned(fsToReceive) then
    fsToReceive.Free;
end;

end.



Aquí la prueba la hice enviando desde el servidor, pero sería lo mismo desde el cliente.

Saludos.

N3Tw0lf

#8
Primero que nada muchas gracias la verdad, pense que nadie se iba a interesar en esto gracias de verdad.

Ahora tengo el problema que no me manda nada es como si nunca leyera nada el socket :huh: la verdad no se, tenia una duda que plantearte en tu codigo no usaste el envio de texto antes que los datos, es por algo en especial? no se necesita identificar lo envio con un texto clave? bueno voy a seguir probando con tu codigo tal vez es una falla mia cualquier cosa vuelvo a preguntar en este mismo post

Muchas gracias de verdad

Saludos

EDITO:
Lo volvi a hacer todo desde el principio las aplicaciones me llegan incompletas  :-( y al querer ejecutarlas me aparece Error el archivo no es una aplicacion WIN32

al compararla con el tamaño del original faltan mas de la mitad de los kb del mismo :s. Disculpame que te joda tanto posta me estas dando una re mano con esto espero que me puedas ayudar a terminarlo

Gracias y saludos


Experiencia es el nombre que le damos a nuestros errores

Khronos14

El código que te puse a mi me funciona perfectamente. En el Form solo tengo un botón, un TClientSocket y un TServerSocket.

Saludos.