Solved

HELP ScktComp File Transfer

Posted on 2009-06-29
9
593 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
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 

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
 
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

Free Tool: Path Explorer

An intuitive utility to help find the CSS path to UI elements on a webpage. These paths are used frequently in a variety of front-end development and QA automation tasks.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

Question has a verified solution.

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

Suggested Solutions

Title # Comments Views Activity
Delphi selector screen 2 92
Slow Restore if incremental backups using RDiff.exe 4 39
Delphi android app hide keyboard 3 47
Get weeknumber and year from date 4 31
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…
Creating an auto free TStringList The TStringList is a basic and frequently used object in Delphi. On many occasions, you may want to create a temporary list, process some items in the list and be done with the list. In such cases, you have to…
Although Jacob Bernoulli (1654-1705) has been credited as the creator of "Binomial Distribution Table", Gottfried Leibniz (1646-1716) did his dissertation on the subject in 1666; Leibniz you may recall is the co-inventor of "Calculus" and beat Isaac…
Nobody understands Phishing better than an anti-spam company. That’s why we are providing Phishing Awareness Training to our customers. According to a report by Verizon, only 3% of targeted users report malicious emails to management. With compan…

726 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