Saturday, 18 November 2017
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协议的应用协议标准,它是在计算机和网络之间交换文件的最简单的方法。
二者都是有用的和常用的,如果纯粹从概念上区分二者就比较费解了,我们直接从功能上进行区分,简单明了:
这两种传输协议也就是合于适配不同的业务和不同的硬件终端。
在使用中,类似于图像、声音等对可靠性要求没有那么高的业务可以用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
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事件触发时执行。
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.
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地址和端口号;在具体应用中是哪种情况,要根据测试结果而定。
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
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.
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
连接路径字符串
包含头文件#include <System.Ioutils.hpp>
Caption= System::Ioutils::TPath::GetDocumentsPath();
"D:\\Users\\Administrator\\Documents"
得到文件清单,文件列表
ListBox1->Items->AddStrings( System::Ioutils::TDirectory::GetFiles(Edit1->Text));
递归文件清单
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 、、
/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
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\PicturesC:\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
Subscribe to:
Posts (Atom)
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...
-
Grows your business with zomok online ordering platform. Zero commission. Suitable for restaurants, kopitiam, food, groceries, pet supplie...
-
Complete TFTP Server example, using Indy components There are not many good TFTP server examples out there, so I wrote this example of...