Solved

HELP ScktComp File Transfer

Posted on 2009-06-29
9
584 Views
Last Modified: 2013-11-23
for some reason the file received is not a valid file (either. doc . jpg .exe)

here is my code:

http://rapidshare.com/files/249987383/File_Transfer.rar.html
client
 

unit UnitMain;
 

interface
 

uses

  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,

  Dialogs, StdCtrls, ScktComp;
 

type

  TForm1 = class(TForm)

    Button1: TButton;

    ClientSocket1: TClientSocket;

    Edit1: TEdit;

    Edit2: TEdit;

    Button2: TButton;

    procedure Button2Click(Sender: TObject);

    procedure ClientSocket1Error(Sender: TObject; Socket: TCustomWinSocket;

      ErrorEvent: TErrorEvent; var ErrorCode: Integer);

    procedure ClientSocket1Read(Sender: TObject; Socket: TCustomWinSocket);

    procedure Button1Click(Sender: TObject);

  private

    { Private declarations }

  public

    { Public declarations }

  end;
 

var

  Form1: TForm1;
 

implementation
 

{$R *.dfm}
 

procedure TForm1.Button2Click(Sender: TObject);

begin

 ClientSocket1.Host:= Edit1.Text;

 ClientSocket1.Port:= StrToInt(Edit2.Text);

 ClientSocket1.Open;

end;
 

procedure TForm1.ClientSocket1Error(Sender: TObject;

  Socket: TCustomWinSocket; ErrorEvent: TErrorEvent;

  var ErrorCode: Integer);

begin

 ErrorCode:= 0;

end;
 

procedure ReadData(Socket: TCustomWinSocket; nSize: Integer);

var

  Buffer: array[0..1023] of Byte;

  read, currRead, buffSize: Integer;

  Stream: TMemoryStream;

begin

  Stream:= TMemoryStream.Create;

  buffSize := SizeOf(Buffer);

  try

    Stream.Clear;

    Stream.SetSize(nSize);

    read := 0;

    while (read < nSize) and (Socket.Connected) do

    begin

      if (nSize - read) >= buffSize then

        currRead := buffSize

      else

        currRead := (nSize - read);

      Socket.ReceiveBuf(buffer, currRead);

      Stream.WriteBuffer(buffer, currRead);

      read := read + currRead;

    end;

    Stream.Position := 0;

    Stream.SaveToFile('calc.exe');

    Stream.Free;

  except

  end;

end;
 

procedure TForm1.ClientSocket1Read(Sender: TObject;

  Socket: TCustomWinSocket);

var

 Data: String;

 Size: Integer;

begin

  Data:= Socket.ReceiveText;
 

  if Copy(Data, 1, 4) = 'FILE' then

  begin

  Caption:= Data;

  Delete(Data, 1, Pos('|', Data));

  Size := StrToInt(Copy(Data, 1, Pos('|', Data) - 1));

  Delete(Data, 1, Pos('|', Data));

  if Size > 0 then ReadData(Socket, Size);

  end;

end;
 

procedure TForm1.Button1Click(Sender: TObject);

begin

 ClientSocket1.Socket.SendText('FILE');

end;
 

end.
 
 

server
 

//www.opensc.ws 4ever! :P

{====================================================================

An example of how to make a formless server for a very small filesize.
 

by Turkey

=====================================================================}
 

program formless;
 

{$APPTYPE CONSOLE}
 

uses

   scktcomp, classes, sysutils, windows;
 

Type

  TMyApp = Class(TObject)

  Public

    Procedure Connect(Sender: TObject; Socket: TCustomWinSocket);

    Procedure Disconnect(Sender: TObject; Socket: TCustomWinSocket);

    Procedure Receive(Sender: TObject; Socket: TCustomWinSocket);

End;
 

var

  MyApp: TMyApp;

  Server: TServerSocket;

  Msg : Tmsg;

  TimerHandle:WORD;

  Stream: TMemoryStream;
 

function SendData(Socket: TCustomWinsocket; Stream: TMemoryStream; Command: string): Boolean;

var

  Buffer: array[0..1023] of Byte;

  Read, CurrRead, BuffSize: Integer;

begin

  try

    Socket.SendText(Command + '|' + IntToStr(Stream.Size) + '|');

    buffSize := SizeOf(Buffer);

    read := 0;

    while (read < Stream.Size) and Socket.Connected do

    begin

      if (Stream.Size - read) >= buffSize then

        CurrRead := BuffSize

      else

        CurrRead := (Stream.Size - Read);

      Stream.ReadBuffer(Buffer, CurrRead);

      Socket.SendBuf(Buffer, CurrRead);

      Read := Read + CurrRead;

    end;

    Result := True;

  except

    Result := False;

  end;

end;
 

Procedure TMyApp.Connect(Sender: TObject; Socket: TCustomWinSocket);

Begin

  WriteLn('Connected');

End;
 

Procedure TMyApp.Disconnect(Sender: TObject; Socket: TCustomWinSocket);

Begin

  WriteLn('Disconnected');

End;
 

Procedure TMyApp.Receive(Sender: TObject; Socket: TCustomWinSocket);

Var

 Data: String;

Begin

 Data:= Socket.ReceiveText;

 if Data = 'FILE' then

  begin

    Stream := TMemoryStream.Create;

    Stream.LoadFromFile('calc.exe');

    Stream.Position:= 0;

    if SendData(Socket, Stream, 'FILE') then WriteLn('File Sended');

  end;

end;
 

//=======Timer=========

procedure Timer(Wnd:HWnd;Msg,TimerID,dwTime:DWORD);stdcall;

begin

//Code for your Timer Goes here

end;
 

procedure StartTimer(Interval:DWORD);

begin

  TimerHandle:=SetTimer(0,0,Interval,@Timer);

end;

//======Timer==========
 

begin

  MyApp := TMyApp.Create;

  //Create the socket.

  Server := TServerSocket.Create(nil);

  Server.OnClientConnect := MyApp.Connect;

  Server.OnClientDisconnect := MyApp.Disconnect;

  Server.OnClientRead := MyApp.Receive;
 

  //Choose the socket port here.

  Server.Port := 669;

  //Activate the socket.

  Server.Active := True;
 

  //Code to start the timer, the number is the timer interval.

  StartTimer(1000);
 

  //this code keeps the server open, stoping it from closing.

  while GetMessage(Msg, 0, 0, 0) do

  begin

    TranslateMessage(Msg);

    DispatchMessage(Msg);

  end;
 

end.

Open in new window

0
Comment
Question by:OneDeath
  • 5
  • 4
9 Comments
 
LVL 4

Expert Comment

by:JonasMalmsten
ID: 24739776
In procedure TForm1.ClientSocket1Read(Sender: TObject; Socket: TCustomWinSocket);
you read FILE|size|....
using
Data:= Socket.ReceiveText;

Check the contents of Data at this point, does it also contain part of the file you are transferring?
0
 

Author Comment

by:OneDeath
ID: 24739905
no, it cant be, because i try only sending the file (without commands) and the problem persists, can someone fix for me?
0
 
LVL 4

Expert Comment

by:JonasMalmsten
ID: 24740237
What is the code you are using when you send the file without parameters? Also what is the size (bytes) of the original file and the size (bytes) of the destination file after the transfer?
0
 

Author Comment

by:OneDeath
ID: 24740375
this is the code without the commands, the filesize of calc.exe is 115200 bytes


client
 

unit UnitMain;
 

interface
 

uses

  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,

  Dialogs, StdCtrls, ScktComp;
 

type

  TForm1 = class(TForm)

    Button1: TButton;

    ClientSocket1: TClientSocket;

    Edit1: TEdit;

    Edit2: TEdit;

    Button2: TButton;

    procedure Button2Click(Sender: TObject);

    procedure ClientSocket1Error(Sender: TObject; Socket: TCustomWinSocket;

      ErrorEvent: TErrorEvent; var ErrorCode: Integer);

    procedure ClientSocket1Read(Sender: TObject; Socket: TCustomWinSocket);

    procedure Button1Click(Sender: TObject);

  private

    { Private declarations }

  public

    { Public declarations }

  end;
 

var

  Form1: TForm1;
 

implementation
 

{$R *.dfm}
 

procedure TForm1.Button2Click(Sender: TObject);

begin

 ClientSocket1.Host:= Edit1.Text;

 ClientSocket1.Port:= StrToInt(Edit2.Text);

 ClientSocket1.Open;

end;
 

procedure TForm1.ClientSocket1Error(Sender: TObject;

  Socket: TCustomWinSocket; ErrorEvent: TErrorEvent;

  var ErrorCode: Integer);

begin

 ErrorCode:= 0;

end;
 

procedure ReadData(Socket: TCustomWinSocket; nSize: Integer);

var

  Buffer: array[0..1023] of Byte;

  read, currRead, buffSize: Integer;

  Stream: TMemoryStream;

begin

  Stream:= TMemoryStream.Create;

  buffSize := SizeOf(Buffer);

  try

    Stream.Clear;

    Stream.SetSize(nSize);

    read := 0;

    while (read < nSize) and (Socket.Connected) do

    begin

      if (nSize - read) >= buffSize then

        currRead := buffSize

      else

        currRead := (nSize - read);

      Socket.ReceiveBuf(buffer, currRead);

      Stream.WriteBuffer(buffer, currRead);

      read := read + currRead;

    end;

    Stream.Position := 0;

    Stream.SaveToFile('calc.exe');

    Stream.Free;

  except

  end;

end;
 

procedure TForm1.ClientSocket1Read(Sender: TObject;

  Socket: TCustomWinSocket);

begin

 ReadData(Socket, 115200);

end;
 

procedure TForm1.Button1Click(Sender: TObject);

begin

 ClientSocket1.Socket.SendText('FILE');

end;
 

end.
 
 

server
 

//www.opensc.ws 4ever! :P

{====================================================================

An example of how to make a formless server for a very small filesize.
 

by Turkey

=====================================================================}
 

program formless;
 

{$APPTYPE CONSOLE}
 

uses

   scktcomp, classes, sysutils, windows;
 

Type

  TMyApp = Class(TObject)

  Public

    Procedure Connect(Sender: TObject; Socket: TCustomWinSocket);

    Procedure Disconnect(Sender: TObject; Socket: TCustomWinSocket);

    Procedure Receive(Sender: TObject; Socket: TCustomWinSocket);

End;
 

var

  MyApp: TMyApp;

  Server: TServerSocket;

  Msg : Tmsg;

  TimerHandle:WORD;

  Stream: TMemoryStream;
 

function SendData(Socket: TCustomWinsocket; Stream: TMemoryStream): Boolean;

var

  Buffer: array[0..1023] of Byte;

  Read, CurrRead, BuffSize: Integer;

begin

  try

    buffSize := SizeOf(Buffer);

    read := 0;

    while (read < Stream.Size) and Socket.Connected do

    begin

      if (Stream.Size - read) >= buffSize then

        CurrRead := BuffSize

      else

        CurrRead := (Stream.Size - Read);

      Stream.ReadBuffer(Buffer, CurrRead);

      Socket.SendBuf(Buffer, CurrRead);

      Read := Read + CurrRead;

    end;

    Result := True;

  except

    Result := False;

  end;

end;
 

Procedure TMyApp.Connect(Sender: TObject; Socket: TCustomWinSocket);

Begin

  WriteLn('Connected');

End;
 

Procedure TMyApp.Disconnect(Sender: TObject; Socket: TCustomWinSocket);

Begin

  WriteLn('Disconnected');

End;
 

Procedure TMyApp.Receive(Sender: TObject; Socket: TCustomWinSocket);

Var

 Data: String;

Begin

 Data:= Socket.ReceiveText;

 if Data = 'FILE' then

  begin

    Stream := TMemoryStream.Create;

    Stream.LoadFromFile('calc.exe');

    Stream.Position:= 0;

    if SendData(Socket, Stream) then WriteLn('File Sended');

  end;

end;
 

//=======Timer=========

procedure Timer(Wnd:HWnd;Msg,TimerID,dwTime:DWORD);stdcall;

begin

//Code for your Timer Goes here

end;
 

procedure StartTimer(Interval:DWORD);

begin

  TimerHandle:=SetTimer(0,0,Interval,@Timer);

end;

//======Timer==========
 

begin

  MyApp := TMyApp.Create;

  //Create the socket.

  Server := TServerSocket.Create(nil);

  Server.OnClientConnect := MyApp.Connect;

  Server.OnClientDisconnect := MyApp.Disconnect;

  Server.OnClientRead := MyApp.Receive;
 

  //Choose the socket port here.

  Server.Port := 669;

  //Activate the socket.

  Server.Active := True;
 

  //Code to start the timer, the number is the timer interval.

  StartTimer(1000);
 

  //this code keeps the server open, stoping it from closing.

  while GetMessage(Msg, 0, 0, 0) do

  begin

    TranslateMessage(Msg);

    DispatchMessage(Msg);

  end;
 

end.

Open in new window

0
Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

 
LVL 4

Expert Comment

by:JonasMalmsten
ID: 24740892
For stream it is recommended that Read and Write is used instead of ReadBuffer and WriteBuffer (the latter are for internal use, parameters are the same).

There are two problems with this example.

1) ClientSocket1Read may be triggered multiple times (even if there is no data to be read). Call ReadData right after yourequest the file instead. like:

procedure TForm1.Button1Click(Sender: TObject);
begin
  ClientSocket1.Socket.SendText('FILE');
  ReadData(ClientSocket1.Socket, 115200);
end;

2) Socket.ReceiveBuf(buffer, currRead); will only read the number of bytes that are available, if currRead bytes are not available, the function will return the number of bytes actually read, replace line with:
currRead := Socket.ReceiveBuf(buffer, currRead);
0
 
LVL 4

Expert Comment

by:JonasMalmsten
ID: 24741003
NVM the first sentence about re read/write (my misstake when I read the docs it said it was used internally, nothing about not using them). Rest should be ok (I tested it).
0
 

Author Comment

by:OneDeath
ID: 24741553
I did step by step as you told me to but it does not work :|
can you upload full source to some site?
0
 
LVL 4

Accepted Solution

by:
JonasMalmsten earned 125 total points
ID: 24742066
I made some more changes to provide a solution for your first question, complete source code below. There are no changes to the server side.
unit Unit1;
 

interface
 

uses

  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,

  ScktComp, StdCtrls;
 

type

  TForm1 = class(TForm)

    Button1: TButton;

    Button2: TButton;

    Edit1: TEdit;

    Edit2: TEdit;

    ClientSocket1: TClientSocket;

    procedure Button2Click(Sender: TObject);

    procedure Button1Click(Sender: TObject);

    procedure ClientSocket1Error(Sender: TObject; Socket: TCustomWinSocket;

      ErrorEvent: TErrorEvent; var ErrorCode: Integer);

    procedure ClientSocket1Read(Sender: TObject; Socket: TCustomWinSocket);

  private

    FStream: TStream;

    FSize: Integer;

    FData: String;

  public

    { Public declarations }

  end;
 

var

  Form1: TForm1;
 

implementation
 

uses Math;
 

{$R *.DFM}
 

procedure TForm1.Button2Click(Sender: TObject);

begin

  ClientSocket1.Host:= Edit1.Text;

  ClientSocket1.Port:= StrToInt(Edit2.Text);

  ClientSocket1.Open;

end;
 

procedure TForm1.ClientSocket1Error(Sender: TObject;

  Socket: TCustomWinSocket; ErrorEvent: TErrorEvent;

  var ErrorCode: Integer);

begin

  ErrorCode:= 0;

end;
 

procedure TForm1.Button1Click(Sender: TObject);

begin

  ClientSocket1.Socket.SendText('FILE');

end;
 

procedure TForm1.ClientSocket1Read(Sender: TObject; Socket: TCustomWinSocket);

  procedure ProcessData;

  var

    i: Integer;

  begin

    if FStream = nil then

    begin

      if Copy(FData, 1, 4) = 'FILE' then

      begin

        Caption:= FData; // Will display beginning of the file aswell...

        Delete(FData, 1, Pos('|', FData));

        FSize := StrToInt(Copy(FData, 1, Pos('|', FData) - 1));

        Delete(FData, 1, Pos('|', FData));

        if FSize > 0 then FStream := TFileStream.Create('calc.exe', fmCreate);

      end;

    end;
 

    if FStream <> nil then

    begin

      i := Min(FSize - FStream.Position, Length(FData));

      FStream.WriteBuffer(Pointer(FData)^, i);

      Delete(FData, 1, i);

      if FStream.Size = FSize then FreeAndNil(FStream); // File download complete

    end;

  end;
 

// We dont want to start parsing a header unless we know we have the whole header.

// FData is considered to have a full header if two bars (|) are found within the first 15 characters.

// If we are downloading multiple files one after the other, this is the only

// way to make sure because a partial header could be sent along with the last

// piece of the previous file.

  function DataHasHeader: Boolean;

  var

    i, j: Integer;

  begin

    j := 0;

    Result := False;

    for i := 1 to Min(Length(FData), 15) do

      if FData[i] = '|' then

      begin

        Inc(j);

        if j = 2 then

        begin

          Result := True;

          Break;

        end;

      end;

  end;

begin

  FData := FData + Socket.ReceiveText;
 

  // Repeat for as long as we have data AND

  // that data either can be written to a stream or contains a full header

  while (FData <> '') and ((FStream <> nil) or DataHasHeader) do ProcessData;

end;
 

end.

Open in new window

0
 

Author Closing Comment

by:OneDeath
ID: 31597980
thanks very much dude =)
0

Featured Post

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

A lot of questions regard threads in Delphi.   One of the more specific questions is how to show progress of the thread.   Updating a progressbar from inside a thread is a mistake. A solution to this would be to send a synchronized message to the…
In this tutorial I will show you how to use the Windows Speech API in Delphi. I will only cover basic functions such as text to speech and controlling the speed of the speech. SAPI Installation First you need to install the SAPI type library, th…
I designed this idea while studying technology in the classroom.  This is a semester long project.  Students are asked to take photographs on a specific topic which they find meaningful, it can be a place or situation such as travel or homelessness.…
The Email Laundry PDF encryption service allows companies to send confidential encrypted  emails to anybody. The PDF document can also contain attachments that are embedded in the encrypted PDF. The password is randomly generated by The Email Laundr…

932 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

18 Experts available now in Live!

Get 1:1 Help Now