Sunday, 12 November 2017

Complete TFTP Server example, using Indy components

Complete TFTP Server example, using Indy components 

There are not many good TFTP server examples out there, so I wrote this example of a multi-thredded TFTP Server, using Indy components.
Answer:

There are few good examples of TFTP servers, so I wrote this complete server as an example.

If works like a Secure TFTP server, since it only allows uploads/downloads from a specific directory.

The example assumes that you open a new project with a new form (Form1), and drop one TFTP Server and TFTP
Client on the form, and two buttons.

The source below can be copied as such. Enjoy.

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, IdBaseComponent, IdComponent, IdUDPBase, IdUDPServer,
  IdTrivialFTPServer, StdCtrls, IdUDPClient, IdTrivialFTP;

type
  TForm1 = class(TForm)
    IdTrivialFTPServer1: TIdTrivialFTPServer;
    IdTrivialFTP1: TIdTrivialFTP;
    Button1: TButton;
    Button2: TButton;
    procedure FormCreate(Sender: TObject);
    procedure IdTrivialFTPServer1ReadFile(Sender: TObject;
      var FileName: string; const PeerInfo: TPeerInfo;
      var GrantAccess: Boolean; var AStream: TStream;
      var FreeStreamOnComplete: Boolean);
    procedure IdTrivialFTPServer1TransferComplete(Sender: TObject;
      const Success: Boolean; const PeerInfo: TPeerInfo; AStream: TStream;
      const WriteOperation: Boolean);
    procedure IdTrivialFTPServer1WriteFile(Sender: TObject;
      var FileName: string; const PeerInfo: TPeerInfo;
      var GrantAccess: Boolean; var AStream: TStream;
      var FreeStreamOnComplete: Boolean);
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
    TFTPPath: string;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
  IdTrivialFTPServer1.ThreadedEvent := True;
  IdTrivialFTPServer1.Active := True;
  { Set the path to where the files will be stored/retreived }
  TFTPPath := IncludeTrailingPathDelimiter('C:\Temp');
end;

procedure TForm1.IdTrivialFTPServer1ReadFile(Sender: TObject;
  var FileName: string; const PeerInfo: TPeerInfo;
  var GrantAccess: Boolean; var AStream: TStream;
  var FreeStreamOnComplete: Boolean);
var
  FS: TFileStream;
begin
  FreeStreamOnComplete := True;
  try
    { Convert UNIX style filenames to WINDOWS style }
    while Pos('/', Filename) <> 0 do
      Filename[Pos('/', Filename)] := '\';
    { Assure that the filename DOES NOT CONTAIN any path information }
    Filename := ExtractFileName(Filename);
    { Check if file exists }
    if FileExists(TFTPPath + Filename) then
    begin
      { Open file in READ ONLY mode }
      FS := TFileStream.Create(TFTPPath + Filename,
        fmOpenRead or fmShareDenyWrite);
      { Assign stream to variable }
      AStream := FS;
      { Set parameters }
      GrantAccess := True;
    end
    else
    begin
      GrantAccess := False;
    end;
  except
    { On errors, deny access }
    GrantAccess := False;
    if Assigned(FS) then
      FreeAndNil(FS);
  end;
end;

procedure TForm1.IdTrivialFTPServer1WriteFile(Sender: TObject;
  var FileName: string; const PeerInfo: TPeerInfo;
  var GrantAccess: Boolean; var AStream: TStream;
  var FreeStreamOnComplete: Boolean);
var
  FS: TFileStream;
begin
  try
    { Convert UNIX style filenames to WINDOWS style }
    while Pos('/', Filename) <> 0 do
      Filename[Pos('/', Filename)] := '\';
    { Assure that the filename DOES NOT CONTAIN any path information }
    Filename := ExtractFileName(Filename);
    { Open file in WRITE ONLY mode }
    FS := TFileStream.Create(TFTPPath + Filename,
      fmCreate or fmShareExclusive);
    { Copy all the data }
    AStream := FS;
    { Set parameters }
    FreeStreamOnComplete := True;
    GrantAccess := True;
  except
    { On errors, deny access }
    GrantAccess := False;
    if Assigned(FS) then
      FreeAndNil(FS);
  end;
end;

procedure TForm1.IdTrivialFTPServer1TransferComplete(Sender: TObject;
  const Success: Boolean; const PeerInfo: TPeerInfo; AStream: TStream;
  const WriteOperation: Boolean);
begin
  // Success = TRUE if the read/write operation was successfull
  // WriteOperation = TRUE if the client SENT a file to the server
  try
    { Close the FileStream }
    if Assigned(AStream) then
      FreeAndNil(AStream);
  except
  end;
end;

// Example of how to DOWNLOAD a file from the server

procedure TForm1.Button1Click(Sender: TObject);
var
  ST: TMemoryStream;
begin
  ST := TMemoryStream.Create;
  IdTrivialFTP1.Get('testfile.dat', ST);
  if Assigned(ST) then
  begin
    ShowMessage('Filesize=' + IntToStr(ST.Size));
    FreeAndNil(ST);
  end;
end;

// Example of how to UPLOAD a file to the server

procedure TForm1.Button2Click(Sender: TObject);
var
  ST: TMemoryStream;
  I: Integer;
  S: string;
begin
  { Create stream }
  ST := TMemoryStream.Create;
  { Initialize data }
  S := 'This is a test file. It whould appear in the ' +
    'TFTP Server''s upload directory.' + #13#10;
  { Store in stream }
  ST.Write(S[1], Length(S));
  ST.Position := 0;
  { Send Stream to TFTP Server }
  IdTrivialFTP1.Put(ST, 'textfile.txt');
  { Free Stream }
  if Assigned(ST) then
    FreeAndNil(ST);
  { Show a dialog }
  ShowMessage('Done!');
end;

end. 


http://code1.okbase.net/codefile/IdTrivialFTPServer.pas_201211268418_275.htm 

https://stackoverflow.com/questions/20614431/can-tidtrivialftp-be-used-for-general-file-transfer-in-delphi 

http://www.delphigroups.info/2/11/212422.html

https://stackoverflow.com/questions/20614431/can-tidtrivialftp-be-used-for-general-file-transfer-in-delphi

http://delphi-kb.blogspot.my/2011/03/complete-tftp-server-example-using-indy.html

 

 

 

 

Friday, 10 November 2017

TCP与UDP的区别用途例子

一.区别
二者都是有用的和常用的,如果纯粹从概念上区分二者就比较费解了,我们直接从功能上进行区分,简单明了:
这两种传输协议也就是合于适配不同的业务和不同的硬件终端。
在使用中,类似于图像、声音等对可靠性要求没有那么高的业务可以用UDP,他们不需要准确存储对准确性无要求但要求速度快。
类似于文本、程序、文件等要求可靠的数据最好就用TCP,但会牺牲一些速度。
对系统资源的要求:CP较多,UDP少。
程序结构:UDP程序结构较简单,TCP复杂。
流模式与数据报模式:TCP保证数据正确性,UDP可能丢包; TCP保证数据顺序,UDP不保证

二.用途
TCP是面向连接的,有比较高的可靠性,一些要求比较高的服务一般使用这个协议,如FTP、Telnet、SMTP、HTTP、POP3等,而UDP是面向无连接的,使用这个协议的常见服务有DNS、SNMP、QQ等。对于QQ必须另外说明一下,QQ2003以前是只使用UDP协议的,其服务器使用8000端口,侦听是否有信息传来,客户端使用4000端口,向外发送信息(这也就不难理解在一般的显IP的QQ版本中显示好友的IP地址信息中端口常为4000或其后续端口的原因了),即QQ程序既接受服务又提供服务,在以后的QQ版本中也支持使用TCP协议了。
Udp是一种面向无连接的通信协议,该协议使得数据传输的速度得到大幅度的提高。视频聊天语音聊天基本都是用UPD协议。

三.例子
TCP: ServerSocket ss = new ServerSocket(2000);
UDP: 创建DatagramSocket对象,DatagramSocket区别于Tcp方式下的socket对象。
DatagramSocket   ds=new   DatagramSocket();
下面是具体的程序代码,已经编译通过,另外附件也是源码可以直接下载。



。。。。


更多TCP和UPD的资料:
TCP---传输控制协议,提供的是面向连接、可靠的字节流服务。当客户和服务器彼此交换数据前,必须先在双方之间建立一个TCP连接,之后才能传输数 据。TCP提供超时重发,丢弃重复数据,检验数据,流量控制等功能,保证数据能从一端传到另一端。

    UDP---用户数据报协议,是一个简单的面向数据报的运输层协议。UDP不提供可靠性,它只是把应用程序传给IP层的数据报发送出去,但是并不能保证它 们能到达目的地。由于UDP在传输数据报前不用在客户和服务器之间建立一个连接,且没有超时重发等机制,故而传输速度很快。

    UDP 与 TCP 的主要区别在于 UDP 不一定提供可靠的数据传输。事实上,该协议不能保证数据准确无误地到达目的地。UDP 在许多方面非常有效。当某个程序的目标是尽快地传输尽可能多的信息时(其中任意给定数据的重要性相对较低),可使用 UDP。ICQ 短消息使用 UDP 协议发送消息。
许多程序将使用单独的TCP连接和单独的UDP连接。重要的状态信息随可靠的TCP连接发送,而主数据流通过UDP发送。

    TCP的目的是提供可靠的数据传输,并在相互进行通信的设备或服务之间保持一个虚拟连接。TCP在数据包接收无序、丢失或在交付期间被破坏时,负责数据恢 复。它通过为其发送的每个数据包提供一个序号来完成此恢复。记住,较低的网络层会将每个数据包视为一个独立的单元,因此,数据包可以沿完全不同的路径发 送,即使它们都是同一消息的组成部分。这种路由与网络层处理分段和重新组装数据包的方式非常相似,只是级别更高而已。
为确保正确地接收数据,TCP要求在目标计算机成功收到数据时发回一个确认(即 ACK)。如果在某个时限内未收到相应的 ACK,将重新传送数据包。如果网络拥塞,这种重新传送将导致发送的数据包重复。但是,接收计算机可使用数据包的序号来确定它是否为重复数据包,并在必要 时丢弃它。

TCP与UDP的选择
    如果比较UDP包和TCP包的结构,很明显UDP包不具备TCP包复杂的可靠性与控制机制。与TCP协议相同,UDP的源端口数和目的端口数也都支持一台 主机上的多个应用。一个16位的UDP包包含了一个字节长的头部和数据的长度,校验码域使其可以进行整体校验。(许多应用只支持UDP,如:多媒体数据 流,不产生任何额外的数据,即使知道有破坏的包也不进行重发。)
    很明显,当数据传输的性能必须让位于数据传输的完整性、可控制性和可靠性时,TCP协议是当然的选择。当强调传输性能而不是传输的完整性时,如:音频和多 媒体应用,UDP是最好的选择。在数据传输时间很短,以至于此前的连接过程成为整个流量主体的情况下,UDP也是一个好的选择,如:DNS交换。把 SNMP建立在UDP上的部分原因是设计者认为当发生网络阻塞时,UDP较低的开销使其有更好的机会去传送管理数据。TCP丰富的功能有时会导致不可预料 的性能低下,但是我们相信在不远的将来,TCP可靠的点对点连接将会用于绝大多数的网络应用。
    FTP协议即文件传输协议,它是一个标准协议,FTP协议也是应用TCP/IP协议的应用协议标准,它是在计算机和网络之间交换文件的最简单的方法。

Thursday, 9 November 2017

http://gomsun2.tistory.com/entry/Indy10-UDP-Sample

http://gomsun2.tistory.com/entry/Indy10-UDP-Sample

http://lifengxi.blog.163.com/blog/static/10348848200823011843243/


http://www.voidcn.com/article/p-zhvdhrvw-bcd.html

https://stackoverflow.com/questions/19763125/udp-file-transfer-using-delphi-indy-10

Wednesday, 8 November 2017

TIdUDPServer控件中文指南

TIdUDPServer控件中文指南


2007-03-15 22:46:28|  分类: delphi程序备忘 |字号 订阅
IdUDPServer
属性
property Bindings: TIdSocketHandles;
用来收集f TIdSocketHandle实例。包含ID_SOCK_DGRAM类型的socket。


property DefaultPort: integer;
监听新连接的端口。


property ThreadedEvent: boolean;
指示UDP读事件的执行方式。是否以线程的形式执行


property Active: Boolean;
是否开始监听。


property Binding: TIdSocketHandle;
只读属性。指示读写传送的socket句柄。


property BroadcastEnabled: Boolean;
是否广播传送数据。


property BufferSize: Integer;
UDP包的尺寸。


property ReceiveTimeout: Integer;
从一个服务中读取数据的超时时间。


property LocalName: string;
本地计算机名称。


property Version: string;
只读属性,用来获取Indy部件的版本号码。


方法
procedure Broadcast(const AData: string; const APort: integer);
在网络上发送数据到所有的计算机。


unction ReceiveBuffer(var ABuffer; const ABufferSize: Integer; const AMSec: Integer =


IdTimeoutDefault): integer; overload;
function ReceiveBuffer(var ABuffer; const ABufferSize: Integer; var VPeerIP: string; var


VPeerPort: integer; AMSec: Integer = IdTimeoutDefault): integer; overload;
从远程连接中读取数据


function ReceiveString(const AMSec: Integer = IdTimeoutDefault): string; overload;
function ReceiveString(var VPeerIP: string; var VPeerPort: integer; const AMSec: Integer =


IdTimeoutDefault): string; overload;
从远程连接中读取数据


procedure Send(AHost: string; const APort: Integer; const AData: string);
向远程计算机系统发送数据。
procedure SendBuffer(AHost: string; const APort: Integer; var ABuffer; const AByteCount:


integer);
向远程计算机系统发送数据


事件
property OnUDPRead: TUDPReadEvent;
UDP读取事件发生时执行。
参数
ABinding
接受UDP数据报的socket。
AData
在UDP数据报中接受数据的流。


property OnStatus: TIdStatusEvent;
指示当前连接状态的句柄。
参数
aaArgs
用来构造当前状态文本消息的格式化参数。
axStatus
当前连接状态。取值范围与TIdUDPClient类中的OnStatus事件相同。


procedure BeginWork(AWorkMode: TWorkMode; const ASize: Integer = 0); virtual;
当OnBeginWork事件触发时执行
AWorkMode可以取的值:
wmRead--从远程连接中读取数据。
wmWrite-- 向远程连接发送数据。


procedure DoWork(AWorkMode: TWorkMode; const ACount: Integer); virtual;
当OnWork事件触发时执行。


procedure EndWork(AWorkMode: TWorkMode); virtual;
当OnEndWork事件触发时执行。

read UDP messages

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, IdSocketHandle, IdBaseComponent,
  IdComponent, IdUDPBase, IdUDPServer, Vcl.StdCtrls;

type
  TForm1 = class(TForm)
    IdUDPServer1: TIdUDPServer;
    Memo1: TMemo;
    procedure FormCreate(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure IdUDPServer1UDPRead(AThread: TIdUDPListenerThread;
      AData: TBytes; ABinding: TIdSocketHandle);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  MyUDPMessage : String;

implementation

{$R *.dfm}

function BytesToString(bytearray: array of byte; len : Integer): String;
var
  a: Integer;
begin
  result := '';
  for a := 0 to len-1 do begin
    result := result + char(bytearray[a]);
  end;
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  Form1.IdUDPServer1.Active := False;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  Form1.IdUDPServer1.DefaultPort := 3333;
  Form1.IdUDPServer1.Active := True;
  Form1.IdUDPServer1.OnUDPRead := IdUDPServer1UDPRead;
end;

procedure TForm1.IdUDPServer1UDPRead(AThread: TIdUDPListenerThread;
  AData: TBytes; ABinding: TIdSocketHandle);
begin
   MyUDPMessage:=BytesToString(AData,10240);
   Memo1.Lines.Add(MyUDPMessage);
end;

end.

通过Indy的IpWatch取得本机IP

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, IdComponent, Vcl.StdCtrls,
  IdBaseComponent, IdIPWatch;

type
  TForm1 = class(TForm)
    IdIPWatch1: TIdIPWatch;
    Edit1: TEdit;
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
     Edit1.Text := IdIPWatch1.LocalIP;
end;

end.

DELPHI中两个UDP控件的用法

[转] http://www.voidcn.com/article/p-qsnisddi-qr.html


DELPHI中有两个UDP控件:TIdUDPServer和TIdUDPClient控件,可用于传输UDP数据;用法都很简单,主要是一些细微的特性,弄清楚了对正确使用这两种控件有很大的好处;下面分别介绍:

一、              TIdUDPServer:代表一个UDP的服务端,接收UDP客户端发过来的数据;在FORM上放置一个TIdUDPServer控件,命名为UDPSvr,在FormCreate事件中编写如下代码:


    UDPSvr.Bindings.Add;

    UDPSvr.Bindings[0].IP := ‘192.168.2.117’;

 UDPSvr.Bindings[0].Port := 1812;

 UDPSvr.Active := True;


在UDPSvr控件的OnUDPRead事件中编写如下代码:

var

    Buffer: array[0..1024] of Char;

    iSize: integer;

    sData: string;

begin

      ZeroMemory(@Buffer,sizeof(Buffer));


      iSize := AData.Size;

      if iSize > 1024 then

      begin

        iSize := 1024;

      end;


      AData.Seek(0,soFromBeginning);

      iSize := AData.Read(Buffer,iSize);

      。。。。。{对接收数据的处理}

end;


这样就完成了一个可以接收数据的UDP应用程序;

其实TIdUDPServer有发送数据的方法:Send和SendBuffer,是继承自TIdUPDBase,所以只要利用TIdUDPServer控件就可完成数据的收发,在FORM上添加一个Tbutton控件,在Click事件中添加如下代码;

var

  Buffer: array[0..1024] of Char;

  sText: string;

  iLen: integer;

begin

  sText := ‘12345678’

  ZeroMemory(@Buffer,sizeof(Buffer));

  StrPCopy(Buffer,sText);

  iLen := Length(sText);


UDPSvr.SendBuffer(‘192.168.2.117’,1814,Buffer,iLen);

end;


            这样就可以向另一UDP应用程序发送数据;


          一个TIdUDPServer控件可以打开多个端口,如下的代码打开了两个端口:

            UDPSvr.Bindings.Add;

            UDPSvr.Bindings[0].IP := GetLocalIP;

            UDPSvr.Bindings[0].Port := 1812;


            UDPSvr.Bindings.Add;

            UDPSvr.Bindings[1].IP := GetLocalIP;

            UDPSvr.Bindings[1].Port := 1813;


            UDPSvr.Active := True;

     

             当打开多个端口时,发送数据是从哪个端口发送出去呢?根据测试结果是:最近收到数据的那个端口;如果还没有收到过数据,则为Bindings[0].Port;

     

            在接收数据的事件中,有一个TidSocketHandle类型的参数:Abinding;这个参数有两对属性:

            IP 、Port:代表本地IP地址和端口;

            PeerIP、PeerPort:代表远端IP地址和端口;

            其中PeerIP、PeerPort在交复发送数据的UDP应用中是很有用的,因为UDP服务端可以向PeerIP和PeerPort回应数据,而不用再去设置UDP客户端的IP地址和端口号(这种方法应用不当,会产生问题,下面会说到);


二、              TIdUDPClient:代表一个UDP的客户端,专门用于发送UDP数据,不能接收数据,因为没有相应的事件和方法;前面已经说过,利用TIdUDPServer控件就可以完成UDP数据的收发,所以一直怀疑TIdUDPClient控件存在的必要性;除非有一个UDP的客户端只发送数据,而从不接收数据,这样的客户端应该很少;后来我想,可能可以用TIdUDPClient控件来分担TIdUDPServer控件的负载,在一个需要收发大量UDP数据的服务端中,TIdUDPServer控件只接收数据,另外专门用一个TIdUDPClient控件发送数据,也许可以提高应用程序的性能(没有经过验证);利用TIdUDPClient发送数据有两种方式:

1、  利用TIdUDPClient控件本身的Send和SendBuffer方法,这时需要设置Host和Port属性,在FORM上放置一个TIdUDPClient控件,命名为:UDPClt;分别设置Host和Port属性值为:192.168.2.117和1814;再编写如下代码:

var

  Buffer: array[0..1024] of Char;

  sText: string;

  iLen: integer;

begin

  sText := ‘12345678’;


  ZeroMemory(@Buffer,sizeof(Buffer));

  StrPCopy(Buffer,sText);

  iLen := Length(sText);


  UDPClt.SendBuffer(Buffer,iLen);

   end;


2、  不需要设置Host和Port属性,而直接利用从TIdUPDBase继承来的Send和SendBuffer方法,也可发送数据,代码如下所示:


UDPClt.SendBuffer(‘192.168.2.117’,1814,Buffer,iLen);


 TIdUDPClient控件发送数据时是通过哪个端口发出去的呢?根据测试的结果:是随机的;这样就给上面说过的UDP服务端可以向PeerIP和PeerPort回应数据造成了麻烦,也就是说如果UDP服务端收到的数据是通过TIdUDPClient控件发过来的,就不能通过PeerIP和PeerPort回应回去,而应设定客户端的IP地址和端口号;在具体应用中是哪种情况,要根据测试结果而定。

Thursday, 2 November 2017

IDUdpServer研究心得

http://www.cnblogs.com/zhmore/archive/2010/08/29/1811921.html

  Indy10中的控件IDUdpServer使用方便,比之Indy9有较大的改动,不过使用的时候一定要先弄清楚它的基本工作流程哦,不然会带来很大的麻烦,一下是本人经过查看源代码及N多测试得出的一些心得:
(1)    使用多线程
把控件的ThreadedEvent设置为true后控件事件就会在绑定线程内执行了,这个多线程给人的感觉好像是每个连接创建一个线程,其实不是这样的。Udp是没有连接概念的,而事实上是每个绑定套接字(Binding:TIdSocketHandle)绑定创建后都会开启一个线程,这个线程专门处理当前绑定套接字的收发工作。
(2)    OnUDPRead事件AThread、ABinding直接的关系
上面我们也说到了每个绑定套接字(Binding:TIdSocketHandle)绑定创建后都会开启一个线程,这样就是说这两个参数是一一对应,每个AThread的线程工作期间只处理当前的绑定套接字的收发。
(3)    Dll内使用IdUdpServer无法执行OnUDPRead事件?

...............


http://www.cnblogs.com/zhmore/archive/2010/08/29/1811921.html

[ Worked ] GetDocument filename ...

unit Unit1;

interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
  FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs,
  IOUtils, FMX.ScrollBox, FMX.Memo, FMX.Controls.Presentation, FMX.StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Memo1: TMemo;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.fmx}

procedure TForm1.Button1Click(Sender: TObject);
var
  DirList: TStringDynArray;
  DirPath: string;
  s: string;
begin                                                  (*
  DirPath := TPath.Combine(TPath.GetDocumentsPath, 'assets');
  DirPath := TPath.Combine(DirPath, 'internal');     *)
  DirPath := TPath.GetSharedCameraPath+'/camera/';

  // Display where we're looking for the files
  Memo1.Lines.Add('Searching ' + DirPath);

  if TDirectory.Exists(DirPath, True) then
  begin
    // Get all files. Non-Windows systems don't typically care about
    // extensions, so we just use a single '*' as a mask.
    DirList := TDirectory.GetFiles(DirPath, '*');

    // If none found, show that in memo
    if Length(DirList) = 0 then
      Memo1.Lines.Add('No files found in ' + DirPath)
    else // Files found. List them.
    begin
      for s in DirList do
        Memo1.Lines.Add(s);
    end;
  end
  else
    Memo1.Lines.Add('Directory ' + DirPath + ' does not exist.');
end;

end.

delphi android路径 TPath 文件路径,文件管理

delphi 新路径、文件功能 IOUtils单元,文件路径,文件管理
http://docwiki.embarcadero.com/RADStudio/Berlin/en/Disk_And_Directory_Support_Routines
http://docwiki.embarcadero.com/RADStudio/XE8/en/Standard_RTL_Path_Functions_across_the_Supported_Target_Platforms
use system.IOUtils
       TPath.GetPicturesPath;
       tpath.GetTempPath;
       TPath.GetMusicPath;
       TPath.GetPicturesPath;
       TPath.GetDocumentsPath;
       TPath.GetDownloadsPath;
       TPath.GetCameraPath;
   system.IOUtils.TPath.GetDocumentsPath;
System.IOUtils.TFile.Copy
  TFile.Create('');
  TDirectory.CreateDirectory('');
 GetSharedDocumentsPath
PathDelim
TPath.DirectorySeparatorChar
 连接路径字符串
TPath.Combine(System.IOUtils.TPath.GetDocumentsPath, afileName)
c++builder 获取Android路径,可以直接用命名空间::写代码
包含头文件#include <System.Ioutils.hpp>
Caption= System::Ioutils::TPath::GetDocumentsPath();
"D:\\Users\\Administrator\\Documents"
得到文件清单,文件列表
 ListBox1->Items->AddStrings( System::Ioutils::TDirectory::GetFiles(Edit1->Text));
递归文件清单
 TStringDynArray sl;
 sl =TDirectory.GetFiles(path, '*.txt', TSearchOption.soAllDirectories);

windows path :
C:\Users\Administrator\Pictures
C:\Users\Administrator\AppData\Local\Temp\
C:\Users\Administrator\Music
D:\Users\Administrator\Documents
C:\Users\Administrator\AppData\Local
C:\Users\Administrator\Pictures
C:\Users\Administrator\AppData\Local
C:\Users\Administrator\AppData\Roaming
C:\ProgramData
C:\Users\Administrator\Videos
C:\Users\Administrator\Music
C:\Users\Administrator\Music
E:\mytest\Win32\Debug\
-------Shared-------
C:\Users\Public\Documents
C:\Users\Public\Pictures
C:\Users\Public\Pictures
C:\Users\Public\Music
C:\Users\Public\Videos
C:\Users\Public\Music
C:\Users\Public\Music
C:\ProgramData
C:\Users\Public\Music
Android Path
/storage/sdcard0/Android/data/com.mm.mtt/files/Pictures
/storage/sdcard0/Android/data/com.mm.mtt/files/tmp
/storage/sdcard0/Android/data/com.mm.mtt/files/Music
/data/data/com.mm.mtt/files 、、GetDocumentsPath

/storage/sdcard0/Android/data/com.mm.mtt/files/Download
/storage/sdcard0/Android/data/com.mm.mtt/files/DCIM
/data/data/com.mm.mtt/cache
/data/data/com.mm.mtt/files 、、GetHomePath
/storage/sdcard0/Android/data/com.mm.mtt/files
/storage/sdcard0/Android/data/com.mm.mtt/files/Movies
/storage/sdcard0/Android/data/com.mm.mtt/files/Ringtones
/storage/sdcard0/Android/data/com.mm.mtt/files/Alarms
/data/app-lib/com.mm.mtt-2
-------Shared-------
/storage/sdcard0/Android/data/com.mm.mtt/files
/storage/sdcard0/Pictures
/storage/sdcard0/DCIM
/storage/sdcard0/Music
/storage/sdcard0/Movies
/storage/sdcard0/Alarms
/storage/sdcard0/Alarms
/storage/sdcard0/Download
/storage/sdcard0/Ringtones

Wednesday, 1 November 2017

how to show the availble files in Android memory with Firemonkey

uses
  IOUtils;

procedure THeaderFooterForm.SpeedButton1Click(Sender: TObject);
var
  DirList: TStringDynArray;
  DirPath: string;
  s: string;
begin
  DirPath := TPath.Combine(TPath.GetDocumentsPath, 'assets');
  DirPath := TPath.Combine(DirPath, 'internal');

  // Display where we're looking for the files
  Memo1.Lines.Add('Searching ' + DirPath);

  if TDirectory.Exists(DirPath, True) then
  begin
    // Get all files. Non-Windows systems don't typically care about
    // extensions, so we just use a single '*' as a mask.
    DirList := TDirectory.GetFiles(DirPath, '*');

    // If none found, show that in memo
    if Length(DirList) = 0 then
      Memo1.Lines.Add('No files found in ' + DirPath)
    else // Files found. List them.
    begin 
      for s in DirList do
        Memo1.Lines.Add(s);
    end;
  end
  else
    Memo1.Lines.Add('Directory ' + DirPath + ' does not exist.');
end;

delphi udp文件传输

http://www.cnblogs.com/MaxWoods/p/3822407.html

客戶端


unit UnitClient;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, IdBaseComponent, IdComponent, IdUDPBase, IdUDPClient,
  IdAntiFreezeBase, IdAntiFreeze, Gauges;

type
  TFormClient = class(TForm)
    IdUDPClient1: TIdUDPClient;
    Edit1: TEdit;
    Label1: TLabel;
    Button1: TButton;
    OpenDialog1: TOpenDialog;
    Gauge1: TGauge;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  FormClient: TFormClient;

implementation

{$R *.dfm}

procedure TFormClient.Button1Click(Sender: TObject);
Var  ReceivedString:String;
  Mem:TFileStream;
  p:Array[0..1023] of byte;
  Posi,Len:Integer;
begin
  if OpenDialog1.Execute then
  begin
    IdUDPClient1.Host:=Edit1.Text;
    IdUDPClient1.Active:=True;
    IdUDPClient1.Send('Send file:File Name:'+OpenDialog1.FileName);
    ReceivedString := IdUDPClient1.ReceiveString();
    if UpperCase(ReceivedString)='RECIVED FILE NAME OK!' then
    begin
      Mem:=TFileStream.Create(OpenDialog1.FileName,fmOpenRead);
      try
        Posi:=0;
        IdUDPClient1.Send('Send File:File Length:'+IntToStr(Mem.Size));
        ReceivedString := IdUDPClient1.ReceiveString();
        if UpperCase(ReceivedString)='RECIVED FILE LENGTH OK!' then
        begin
          While Posi<Mem.Size do//一次只发1024个字节,字节数不能太多,不过应该还可以增加一些.
          begin
            Len:=1024;
            if Mem.Size-Posi<1024 then
              Len:=Mem.Size-Posi;
            Mem.Read(p,Len);
            IdUDPClient1.SendBuffer(P,Len);
            Inc(Posi,Len);
            Gauge1.Progress:=Round(Posi/Mem.Size*100);
            ReceivedString := IdUDPClient1.ReceiveString();
            if UpperCase(ReceivedString)<>'RECIVED FILE PACKAGE OK!' then
              Break;
            Application.ProcessMessages;
          end;
          IdUDPClient1.Send('Send File:File End!');
        end else
          ShowMessage('Send file cancel!');
      finally
        Mem.Free;
      end;
    end;
  end;
end;

end.

服务器端

unit UnitServer;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, IdBaseComponent, IdComponent, IdUDPBase, IdUDPServer,IdSocketHandle,
  IdAntiFreezeBase, IdAntiFreeze, Gauges;

type
  TFormServer = class(TForm)
    IdUDPServer1: TIdUDPServer;
    SaveDialog1: TSaveDialog;
    Gauge1: TGauge;
    procedure IdUDPServer1UDPRead(Sender: TObject; AData: TStream;ABinding: TIdSocketHandle);
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    FileName:String;
    FileSize:Integer;
    Mem:TFileStream;
    { Private declarations }
  public
    { Public declarations }
  end;

var
  FormServer: TFormServer;

implementation

{$R *.dfm}

procedure TFormServer.IdUDPServer1UDPRead(Sender: TObject; AData: TStream;
  ABinding: TIdSocketHandle);
Var Str:String;
begin
  AData.Seek(0,0);
  SetLength(Str,AData.Size);
  AData.Read(Str[1],AData.Size);
  if Pos('Send file:File Name:',Str)>0 then
  begin
    Delete(Str,1,Length('Send file:File Name:'));
    FileName:=Str;
    Str:='Recived File Name OK!';
    ABinding.SendTo(ABinding.PeerIP, ABinding.PeerPort, Str[1], Length(Str));
  end else if Pos('Send File:File Length:',Str)>0 then
  begin
    Delete(Str,1,Length('Send File:File Length:'));
    FileSize:=StrToIntDef(Str,0);
    SaveDialog1.FileName:=FileName;
    if SaveDialog1.Execute then
    begin
      FileName:=SaveDialog1.FileName;
      if FileExists(FileName) then
        DeleteFile(FileName);
      if Mem<>nil then
      begin
        Mem.Free;
        Mem:=nil;
      end;
      if not FileExists(FileName) then
        Mem:=TFileStream.Create(FileName,fmOpenReadWrite or fmCreate)
      else
        Mem:=TFileStream.Create(FileName,fmOpenReadWrite);
      Str:='Recived File Length OK!';
      ABinding.SendTo(ABinding.PeerIP, ABinding.PeerPort, Str[1], Length(Str));
    end else
    begin
      Str:='Recived File Length Cancel!';
      ABinding.SendTo(ABinding.PeerIP, ABinding.PeerPort, Str[1], Length(Str));
    end;
  end else if Pos('Send File:File End!',Str)>0 then
  begin
    if Mem<>nil then
    begin
      Mem.Free;
      Mem:=nil;
      Str:='Recived File OK!';
      ABinding.SendTo(ABinding.PeerIP, ABinding.PeerPort, Str[1], Length(Str));
    end;
    FileName:='';
    FileSize:=0;
  end
  else
  begin
    if Mem<>nil then
    begin
      Mem.Seek(0,2);
      AData.Seek(0,0);
      Mem.CopyFrom(AData,AData.Size);
      Gauge1.Progress:=Round(Mem.Size/FileSize*100);
      Str:='Recived File Package OK!';
      ABinding.SendTo(ABinding.PeerIP, ABinding.PeerPort, Str[1], Length(Str));
      Application.ProcessMessages;
    end;
  end;
end;

procedure TFormServer.FormCreate(Sender: TObject);
begin
  IdUDPServer1.Active:=True;
  FileName:='';
  FileSize:=0;
  Mem:=nil;
end;

procedure TFormServer.FormDestroy(Sender: TObject);
begin
  if Mem<>nil then
    Mem.Free;
end;

end.









procedure TGisMapForm.SetAllVidIconXY;
var i: Integer;
  X, Y: Integer;
begin
    for i := Low(VI) to High(VI) do
        if VI[i].Img.Visible then
        begin
            GetOffsetXY(VI[i].X, VI[i].Y, X, Y);
            VI[i].Img.Left := X;
            VI[i].Img.Top := Y;
            VI[i].Img.Repaint;
        end;
end;

procedure TGisMapForm.GetOffsetXY(X: Integer; Y: Integer; var OffSetX: integer; var OffSetY: Integer);
var
    ZM: Double; //缩放度
    VX, VY: Integer;
    OX, OY: Integer;
begin
    ZM := Map.Zoom;
    VX := Map.ViewX;
    VY := Map.ViewY;
    OX := Map.OffsetX;
    OY := Map.OffsetY;
    OffSetX := Round(X * ZM / 100 - VX + OX);
    OffSetY := Round(Y * ZM / 100 - VY + OY);
end;


procedure TGisMapForm.UnderGetOffsetXY(OffSetX: integer; OffSetY: Integer;var X: Integer;var  Y: Integer);
var
    ZM: Double; //缩放度
    VX, VY: Integer;
    OX, OY: Integer;
begin
    ZM := Map.Zoom;
    VX := Map.ViewX;
    VY := Map.ViewY;
    OX := Map.OffsetX;
    OY := Map.OffsetY;
    X:=Round((OffSetX+VX- OX)* 100 / ZM);
    Y:=Round((OffSetY+VY- OY)* 100 /ZM);
end;

也可參考 https://wenku.baidu.com/view/e167fc68011ca300a6c39053.html 

zomok E-commerce system plan. Choose your online ordering system. No-risk 30 day free trial. Then USD 9/month. No credit card required.

zomok E-commerce system plan. Choose your online ordering system. No-risk 30 day free trial. Then USD 9/month. No credit card required. h...