Solved

HELP ScktComp File Transfer

Posted on 2009-06-29
9
581 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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

 
LVL 4

Expert Comment

by:JonasMalmsten
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
thanks very much dude =)
0

Featured Post

Highfive Gives IT Their Time Back

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

Introduction The parallel port is a very commonly known port, it was widely used to connect a printer to the PC, if you look at the back of your computer, for those who don't have newer computers, there will be a port with 25 pins and a small print…
In my programming career I have only very rarely run into situations where operator overloading would be of any use in my work.  Normally those situations involved math with either overly large numbers (hundreds of thousands of digits or accuracy re…
In this seventh video of the Xpdf series, we discuss and demonstrate the PDFfonts utility, which lists all the fonts used in a PDF file. It does this via a command line interface, making it suitable for use in programs, scripts, batch files — any pl…
This video explains how to create simple products associated to Magento configurable product and offers fast way of their generation with Store Manager for Magento tool.

763 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

10 Experts available now in Live!

Get 1:1 Help Now