怎样在局域网内传输exe文件?郁闷了,这方面资料我都找不到哦,兄弟们帮忙哦 怎样在局域网内传输exe文件?郁闷了,这方面资料我都找不到哦,兄弟们帮忙哦我的qq25549894 邮箱[email protected] 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 从www.2ccc.com或www.delphifans.com上找源码,肯定有,我见过~ socket 编程么?下面这个是我自己写得 demo 希望能帮到你哦。---------------------------------【原创】『局域网内』 TCP传文件的demo源码分析--server端最近在写一个 聊天室程序,因为其中用到点对点传文件这个应该是比较典型的文件传输程序,相信会对一些传输文件的朋友有帮助。所以便贴了出来,其中对于文件流的传输处理比较有意义的这个demo是 客户端(client)----->服务端(server) 采用的是TCP协议,实现多播稳定传输大文件。原来我以为是 UDP协议的呢一看 原来是 TCP的 赫赫 不管他 分析一下 其中对文件流的操作部分值得借鉴下面 我将我对代码的理解 主要是比较难明白的部分做一下旁注,也算是学习笔记,贴出来希望能对新手有帮助,对高手呢 也有启发作用 :)双斜杠以后是我的注释--------------------------------------总的思路,就是客户端朝服务端发送数据流,然后按照顺序一个一个发过来的,然后,服务端也是一个一个接受,按顺序一个一个读,直到读完为止。--------------------------------------- //先看 server端的代码unit uServer;interfaceuses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ComCtrls, ExtDlgs, IdBaseComponent, IdComponent, IdTCPServer;type TDataState = (dstNone, dstReceiving); //定义一个枚举类型TDataState,其中只有两个值dstNone和dstReceiving //定义TThreadData类型,其对象用来保存一个连接的状态以及一些变量//以下的定义其实相当于自己定义了一个控件 TThreadData ,里面有自己的方法和属性TThreadData = class private //--------------------私有方法属性 FState: TDataState; //--------------属性FState,类型为前面定义的枚举型 FFileSize: Integer; //--------------属性FFileSize,整型 FStream: TFileStream; //------------属性FStream,TFileStream类型 procedure SetState(const Value: TDataState); // ---------方法SetState procedure SetFileSize(const Value: Integer); // ---------方法SetFileSize procedure SetStream(const Value: TFileStream);// --------方法SetStream public //公有方法属性 constructor Create; //---------------构造方法,主要是用于该类型的对象生成 destructor Destroy; override; //-----------析构方法,主要用于该类型的对象的注销 property State : TDataState read FState write SetState; //-------属性State定义 property FileSize : Integer read FFileSize write SetFileSize; //------属性FileSize 定义 property Stream : TFileStream read FStream write SetStream;//-----属性stream定义 end;//接下来就是 主窗口的组件创建和定义了type TfmServer = class(TForm) //定义了一个窗口 类TfmServer ProgressBar1: TProgressBar; //在里面放进进度显示条ProgressBar1: IdTCPServer1: TIdTCPServer; //放一个IdTCPServer控件 IdTCPServer1 //下面两个是 indy控件IdTCPServer的两个方法,一个是建立连接时用,一个是接受传输时用 procedure IdTCPServer1Connect(AThread: TIdPeerThread); procedure IdTCPServer1Execute(AThread: TIdPeerThread); private { Private declarations } public { Public declarations } end;var fmServer: TfmServer; //窗口建立implementation{$R *.dfm}procedure TfmServer.IdTCPServer1Connect(AThread: TIdPeerThread);begin AThread.Data := TThreadData.Create; //看到了吧,AThread.Data 就是利用TThreadData里的构造方法创建的对象 with AThread.Data as TThreadData do begin State := dstNone; end;//上面这段是用来设置对象AThread.Data里的属性State的值为 dstNone ,这个属性表示目前有没有正在接受文件传输,刚开启服务监听,连接是没有的,所以赋值dstNone end;//下面这个事件Execute是表示 有数据传过来的时候的执行内容,是IdTCPServer的一个方法procedure TfmServer.IdTCPServer1Execute(AThread: TIdPeerThread);var //下面定义一些局部变量 aFileSize : Integer; //aFileSize用来表示文件大小,整型 aFileName : String; //aFileName表示文件名,字串型 Buff : array[0..1023] of Byte; // Buff 缓存区大小设置,byte型 ReadCount : Integer; //实际每次读取文件块的大小,整型begin with AThread.Data as TThreadData do //针对对AThread.Data对象 进行操作(程序块) begin if State = dstNone then //如果AThread.Data状态属性为dstNone ,即没人连接时 begin if not AThread.Terminated and AThread.Connection.Connected then //如果有连接时 begin //读取文件名 aFileName := AThread.Connection.ReadLn(#13#10, 100); //如果读到文件名为空就退出 if aFileName = '' then Exit; AThread.Connection.WriteLn;//---返回确认文件传输标志,和前面的Readln相互对应 AThread.Connection.ReadBuffer(aFileSize, 4);----//开始读取文件长度,放进变量aFileSize中 FileSize := aFileSize; ProgressBar1.Max := FileSize; Stream := TFileStream.Create(aFileName, fmCreate);//创建一个文件流 State := dstReceiving; end end; //以下是如果有连接时进行数据块的读取并且用文件流写入文件中 if not AThread.Terminated and AThread.Connection.Connected then begin //读取文件流 repeat //这里确定每次读取的文件块长度,如果剩余长度比长度长就用自定义的 buff否则用剩余的长度 if FileSize - Stream.Size > SizeOf(Buff) then ReadCount := SizeOf(Buff) else ReadCount := FileSize - Stream.Size; AThread.Connection.ReadBuffer(Buff, ReadCount); //从连接中读取 ReadCount长度的文件块放到缓冲区Buff,中 Stream.WriteBuffer(Buff, ReadCount); //将缓冲区中的内容写进文件流中,这是就是写到文件aFileName中啦 ProgressBar1.Position := Stream.Size; //文件流当前写的大小,值赋给进度条的位置 Caption := IntToStr(Stream.Size) + '/' + IntToStr(FileSize); //显示已经传输和实际文件大小的比例 Application.ProcessMessages; //这句作用是让消息传递动态显示起来,如果没有这句上面的caption是不会显示跳动的 until Stream.Size >= FileSize; //直到文件大小和原文件大小一致结束循环 AThread.Connection.WriteLn('OK'); //返回一个信息 OK,让客户端知道你读完了 //释放一些文件流内存 Stream.Free; Stream := nil; //定义成没有人连接,准备接受下一个人的连接 State := dstNone; end; end; end;{ TThreadData }//下面是 TThreadData 的 几个方法和属性的定义,看看就明白了吧constructor TThreadData.Create;begin inherited; Stream := nil;end;destructor TThreadData.Destroy;begin if Assigned(Stream) then Stream.Free; inherited;end;procedure TThreadData.SetFileSize(const Value: Integer);begin FFileSize := Value;end;procedure TThreadData.SetState(const Value: TDataState);begin FState := Value;end;procedure TThreadData.SetStream(const Value: TFileStream);begin FStream := Value;end;end. 接下来 我把我精简分解出来的代码并测试成功的代码 公布出来请对比一下 上面的客户端代码 看看区别在哪里?帖子末尾我告诉你赫赫--------改写的服务端-------------unit server;interfaceuses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, Buttons, ComCtrls, IdBaseComponent, IdComponent, IdTCPServer;type TDataState = (dstNone, dstReceiving); TForm1 = class(TForm) IdTCPServer1: TIdTCPServer; ProgressBar1: TProgressBar; SpeedButton1: TSpeedButton; StaticText1: TStaticText; StaticText2: TStaticText; StaticText3: TStaticText; StaticText4: TStaticText; SpeedButton2: TSpeedButton; procedure SpeedButton1Click(Sender: TObject); procedure SpeedButton2Click(Sender: TObject); procedure IdTCPServer1Connect(AThread: TIdPeerThread); procedure IdTCPServer1Execute(AThread: TIdPeerThread); private { Private declarations } public { Public declarations } end;var Form1: TForm1; State:TDataState;implementation{$R *.dfm}procedure TForm1.SpeedButton1Click(Sender: TObject);begin IdTCPServer1.Active:=true; StaticText4.Caption:='服务启动';end;procedure TForm1.SpeedButton2Click(Sender: TObject);begin IdTCPServer1.Active:=false; StaticText4.Caption:='服务停止';end;procedure TForm1.IdTCPServer1Connect(AThread: TIdPeerThread);begin State := dstNone;end;procedure TForm1.IdTCPServer1Execute(AThread: TIdPeerThread);var //下面定义一些局部变量 aFileSize : Integer; //aFileSize用来表示文件大小,整型 aFileName : String; //aFileName表示文件名,字串型 Buff : array[0..1023] of Byte; // Buff 缓存区大小设置,byte型 ReadCount : Integer; //实际每次读取文件块的大小,整型 Stream : TFileStream; begin Stream:=nil; if State = dstNone then begin if not AThread.Terminated and AThread.Connection.Connected then begin aFileName := AThread.Connection.ReadLn(#13#10, 100); if aFileName = '' then Exit; AThread.Connection.WriteLn; AThread.Connection.ReadBuffer(aFileSize, 4);//开始读取文件长度,放进变量aFileSize中 ProgressBar1.Max := aFileSize; Stream := TFileStream.Create(aFileName, fmCreate);//创建一个文件流 State := dstReceiving; end ; end; if not AThread.Terminated and AThread.Connection.Connected then begin //读取文件流 repeat if aFileSize - Stream.Size > SizeOf(Buff) then ReadCount := SizeOf(Buff) else ReadCount := aFileSize - Stream.Size; AThread.Connection.ReadBuffer(Buff, ReadCount); //从连接中读取 ReadCount长度的文件块放到缓冲区Buff,中 Stream.WriteBuffer(Buff, ReadCount); //将缓冲区中的内容写进文件流中,这是就是写到文件aFileName中啦 ProgressBar1.Position := Stream.Size; //文件流当前写的大小,值赋给进度条的位置 Caption := IntToStr(Stream.Size) + '/' + IntToStr(aFileSize); //显示已经传输和实际文件大小的比例 Application.ProcessMessages; //这句作用是让消息传递动态显示起来,如果没有这句上面的caption是不会显示跳动的 until Stream.Size >= aFileSize; //直到文件大小和原文件大小一致结束循环 AThread.Connection.WriteLn('OK'); //返回一个信息 OK,让客户端知道你读完了 //释放一些文件流内存 end; Stream.Free; //Stream:=nil; //定义成没有人连接,准备接受下一个人的连接 State:= dstNone;end;end.-----服务端代码结束------细心的朋友已经看出区别了吧,我改写后的代码是看着简单直接了,但是却没法多播接受文件,因为是只能接受单播(同一个时刻只能接受一个客户端的连接)的传输。所以说 ,前面的demo是先自定义了一个类 TThreadData 别小看这个类哦,其实这个类定义出来以后传播过来的文件就不会混淆,因为各自是独立的,就是说每个客户端连接过来,都会生成一个这样的类对象,作者目的是什么呢,其实就是为了让各个客户端独立起来,否则,大家都往一个服务端传文件的时候,就会所有的数据块混杂在一起了!那么我为什么要精简他呢,目的只有一个,想测试一下核心代码,因为我还要写一个精简出来的客户端,所以这个服务端就是我特意测试用来写的。-------------------ok!接下来看我精简分解出来的客户端代码 在看代码之前提醒一下,请注意,我这个IdTCPClient组件对象是动态创建的,在Button1Click事件里大家也可以看到动态创建一些对象的方法。这个是我改写的实现 传输文件的 局域网内程序。。用来做数据备份的朋友应该可以使用哦在外网如果是公网IP估计也是可以使用的记住测试的时候 要在客户端目录里 放一个大文件 test.rar 在服务端目录下就会生成一个同样的文件了,这就是传输过来生成的。这个程序只是一个demo用来讲解 idtcpclient 如何 朝 Idtcpserver 传输文件效率还有些问题,就是运行时 感觉本地机器CPU会比较高,就像复制文件一样 赫赫 如何解决这样的问题呢?如果有朋友知道的话 一起探讨一下哦!------------客户端代码--------------------unit Unit1;interfaceusesWindows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient, StdCtrls;type TForm1 = class(TForm) Button1: TButton; procedure Button1Click(Sender: TObject); private { Private declarations } public { Public declarations } end;var Form1: TForm1; Buf : array[0..1023] of Byte; aSize, ReadCount, Tmpint : Integer; aStream : TFileStream; aIdTCPClient: TIdTCPClient; FFileName:string;implementation{$R *.dfm}procedure TForm1.Button1Click(Sender: TObject);begin FFileName:='test.rar'; aStream := nil; aIdTCPClient := nil; try aStream := TFileStream.Create(FFileName, fmOpenRead or fmShareDenyWrite); aIdTCPClient := TIdTCPClient.Create(Application); aIdTCPClient.Port := 5432; aIdTCPClient.Host := '127.0.0.1'; aIdTCPClient.Connect(5000); //发送文件名 aIdTCPClient.WriteLn(ExtractFileName(FFileName)); //等待接受确认 aIdTCPClient.ReadLn(#13#10, 1000); //写文件长度和文件流 aSize := aStream.Size; aIdTCPClient.WriteBuffer(aSize, 4); while aStream.Position < aStream.Size do begin if aStream.Size - aStream.Position >= SizeOf(Buf) then ReadCount := sizeOf(Buf) else ReadCount := aStream.Size - aStream.Position; aStream.ReadBuffer(Buf, ReadCount); aIdTCPClient.WriteBuffer(Buf, ReadCount); end; aIdTCPClient.ReadLn; aIdTCPClient.Disconnect; finally aIdTCPClient.Disconnect; if aStream<>nil then FreeAndNil(aStream); if aIdTCPClient<>nil then FreeAndNil(aIdTCPClient); end;end;end. DBGRIDEH能否禁止选择其他记录操作的同时可以拉动水平滚动条 还有侠客和剑客吗???快来帮啊!!!!!!!!!!!!急!!!!! ADO 的事务 求购二手笔记本 dbgrideh控件的字段求和问题 大家帮我看看 请教 关于 Access2007 压缩后的排序问题 请教Delphi 文件处理(关于文档格式、变长结构体在文件中存取、文档中回车换行处理) 请问斑竹及所有人,怎样得到QuickReport的总页数? 有关QuickRep的问题 Delphi 折半查找法 关于组件
www.2ccc.com或www.delphifans.com上找源码,肯定有,我见过~
socket 编程么?下面这个是我自己写得 demo 希望能帮到你哦。---------------------------------
【原创】『局域网内』 TCP传文件的demo源码分析--server端最近在写一个 聊天室程序,因为其中用到点对点传文件
这个应该是比较典型的文件传输程序,相信会对一些传输文件的朋友有帮助。
所以便贴了出来,其中对于文件流的传输处理比较有意义的
这个demo是 客户端(client)----->服务端(server) 采用的是TCP协议,实现多播稳定传输大文件。原来我以为是 UDP协议的呢
一看 原来是 TCP的 赫赫 不管他 分析一下 其中对文件流的操作部分值得借鉴下面 我将我对代码的理解 主要是比较难明白的部分做一下旁注,也算是学习笔记,贴出来希望能对新手有帮助,对高手呢 也有启发作用 :)双斜杠以后是我的注释
--------------------------------------总的思路,就是客户端朝服务端发送数据流,然后按照顺序一个一个发过来的,然后,服务端也是一个一个接受,按顺序一个一个读,直到读完为止。
---------------------------------------
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ComCtrls, ExtDlgs, IdBaseComponent, IdComponent, IdTCPServer;type TDataState = (dstNone, dstReceiving);
//定义一个枚举类型TDataState,其中只有两个值dstNone和dstReceiving
//定义TThreadData类型,其对象用来保存一个连接的状态以及一些变量
//以下的定义其实相当于自己定义了一个控件 TThreadData ,里面有自己的方法和属性TThreadData = class
private //--------------------私有方法属性
FState: TDataState; //--------------属性FState,类型为前面定义的枚举型
FFileSize: Integer; //--------------属性FFileSize,整型
FStream: TFileStream; //------------属性FStream,TFileStream类型 procedure SetState(const Value: TDataState); // ---------方法SetState
procedure SetFileSize(const Value: Integer); // ---------方法SetFileSize
procedure SetStream(const Value: TFileStream);// --------方法SetStream
public //公有方法属性
constructor Create; //---------------构造方法,主要是用于该类型的对象生成
destructor Destroy; override; //-----------析构方法,主要用于该类型的对象的注销 property State : TDataState read FState write SetState; //-------属性State定义
property FileSize : Integer read FFileSize write SetFileSize; //------属性FileSize 定义
property Stream : TFileStream read FStream write SetStream;//-----属性stream定义
end;//接下来就是 主窗口的组件创建和定义了type
TfmServer = class(TForm) //定义了一个窗口 类TfmServer
ProgressBar1: TProgressBar; //在里面放进进度显示条ProgressBar1:
IdTCPServer1: TIdTCPServer; //放一个IdTCPServer控件 IdTCPServer1 //下面两个是 indy控件IdTCPServer的两个方法,一个是建立连接时用,一个是接受传输时用
procedure IdTCPServer1Connect(AThread: TIdPeerThread);
procedure IdTCPServer1Execute(AThread: TIdPeerThread);
private
{ Private declarations }
public
{ Public declarations }
end;var
fmServer: TfmServer; //窗口建立implementation{$R *.dfm}procedure TfmServer.IdTCPServer1Connect(AThread: TIdPeerThread);
begin AThread.Data := TThreadData.Create; //看到了吧,AThread.Data 就是利用TThreadData里的构造方法创建的对象
with AThread.Data as TThreadData do
begin
State := dstNone;
end;//上面这段是用来设置对象AThread.Data里的属性State的值为 dstNone ,这个属性表示目前有没有正在接受文件传输,刚开启服务监听,连接是没有的,所以赋值dstNone
end;
//下面这个事件Execute是表示 有数据传过来的时候的执行内容,是IdTCPServer的一个方法procedure TfmServer.IdTCPServer1Execute(AThread: TIdPeerThread);var //下面定义一些局部变量
aFileSize : Integer; //aFileSize用来表示文件大小,整型
aFileName : String; //aFileName表示文件名,字串型
Buff : array[0..1023] of Byte; // Buff 缓存区大小设置,byte型
ReadCount : Integer; //实际每次读取文件块的大小,整型
begin with AThread.Data as TThreadData do //针对对AThread.Data对象 进行操作(程序块)
begin
if State = dstNone then //如果AThread.Data状态属性为dstNone ,即没人连接时
begin
if not AThread.Terminated and AThread.Connection.Connected then //如果有连接时
begin
//读取文件名
aFileName := AThread.Connection.ReadLn(#13#10, 100);
//如果读到文件名为空就退出
if aFileName = '' then
Exit;
AThread.Connection.WriteLn;//---返回确认文件传输标志,和前面的Readln相互对应
AThread.Connection.ReadBuffer(aFileSize, 4);----//开始读取文件长度,放进变量aFileSize中
FileSize := aFileSize;
ProgressBar1.Max := FileSize;
Stream := TFileStream.Create(aFileName, fmCreate);//创建一个文件流
State := dstReceiving;
end end; //以下是如果有连接时进行数据块的读取并且用文件流写入文件中
if not AThread.Terminated and AThread.Connection.Connected then
begin
//读取文件流
repeat
//这里确定每次读取的文件块长度,如果剩余长度比长度长就用自定义的 buff否则用剩余的长度
if FileSize - Stream.Size > SizeOf(Buff) then
ReadCount := SizeOf(Buff)
else
ReadCount := FileSize - Stream.Size; AThread.Connection.ReadBuffer(Buff, ReadCount); //从连接中读取 ReadCount长度的文件块放到缓冲区Buff,中 Stream.WriteBuffer(Buff, ReadCount); //将缓冲区中的内容写进文件流中,这是就是写到文件aFileName中啦 ProgressBar1.Position := Stream.Size; //文件流当前写的大小,值赋给进度条的位置
Caption := IntToStr(Stream.Size) + '/' + IntToStr(FileSize); //显示已经传输和实际文件大小的比例 Application.ProcessMessages; //这句作用是让消息传递动态显示起来,如果没有这句上面的caption是不会显示跳动的 until Stream.Size >= FileSize; //直到文件大小和原文件大小一致结束循环
AThread.Connection.WriteLn('OK'); //返回一个信息 OK,让客户端知道你读完了
//释放一些文件流内存
Stream.Free;
Stream := nil;
//定义成没有人连接,准备接受下一个人的连接
State := dstNone;
end;
end;
end;{ TThreadData }
//下面是 TThreadData 的 几个方法和属性的定义,看看就明白了吧
constructor TThreadData.Create;
begin
inherited;
Stream := nil;
end;destructor TThreadData.Destroy;
begin
if Assigned(Stream) then
Stream.Free;
inherited;
end;procedure TThreadData.SetFileSize(const Value: Integer);
begin
FFileSize := Value;
end;procedure TThreadData.SetState(const Value: TDataState);
begin
FState := Value;
end;procedure TThreadData.SetStream(const Value: TFileStream);
begin
FStream := Value;
end;end.
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, Buttons, ComCtrls, IdBaseComponent, IdComponent,
IdTCPServer;type
TDataState = (dstNone, dstReceiving);
TForm1 = class(TForm)
IdTCPServer1: TIdTCPServer;
ProgressBar1: TProgressBar;
SpeedButton1: TSpeedButton;
StaticText1: TStaticText;
StaticText2: TStaticText;
StaticText3: TStaticText;
StaticText4: TStaticText;
SpeedButton2: TSpeedButton;
procedure SpeedButton1Click(Sender: TObject);
procedure SpeedButton2Click(Sender: TObject);
procedure IdTCPServer1Connect(AThread: TIdPeerThread);
procedure IdTCPServer1Execute(AThread: TIdPeerThread);
private
{ Private declarations }
public
{ Public declarations }
end;var
Form1: TForm1;
State:TDataState;implementation{$R *.dfm}procedure TForm1.SpeedButton1Click(Sender: TObject);
begin
IdTCPServer1.Active:=true;
StaticText4.Caption:='服务启动';
end;procedure TForm1.SpeedButton2Click(Sender: TObject);
begin
IdTCPServer1.Active:=false;
StaticText4.Caption:='服务停止';
end;procedure TForm1.IdTCPServer1Connect(AThread: TIdPeerThread);
begin
State := dstNone;
end;procedure TForm1.IdTCPServer1Execute(AThread: TIdPeerThread);
var //下面定义一些局部变量
aFileSize : Integer; //aFileSize用来表示文件大小,整型
aFileName : String; //aFileName表示文件名,字串型
Buff : array[0..1023] of Byte; // Buff 缓存区大小设置,byte型
ReadCount : Integer; //实际每次读取文件块的大小,整型
Stream : TFileStream;
begin
Stream:=nil;
if State = dstNone then
begin
if not AThread.Terminated and AThread.Connection.Connected then
begin
aFileName := AThread.Connection.ReadLn(#13#10, 100);
if aFileName = '' then
Exit;
AThread.Connection.WriteLn;
AThread.Connection.ReadBuffer(aFileSize, 4);//开始读取文件长度,放进变量aFileSize中
ProgressBar1.Max := aFileSize; Stream := TFileStream.Create(aFileName, fmCreate);//创建一个文件流
State := dstReceiving;
end ;
end; if not AThread.Terminated and AThread.Connection.Connected then
begin
//读取文件流
repeat if aFileSize - Stream.Size > SizeOf(Buff) then
ReadCount := SizeOf(Buff)
else
ReadCount := aFileSize - Stream.Size; AThread.Connection.ReadBuffer(Buff, ReadCount); //从连接中读取 ReadCount长度的文件块放到缓冲区Buff,中 Stream.WriteBuffer(Buff, ReadCount); //将缓冲区中的内容写进文件流中,这是就是写到文件aFileName中啦 ProgressBar1.Position := Stream.Size; //文件流当前写的大小,值赋给进度条的位置
Caption := IntToStr(Stream.Size) + '/' + IntToStr(aFileSize); //显示已经传输和实际文件大小的比例 Application.ProcessMessages; //这句作用是让消息传递动态显示起来,如果没有这句上面的caption是不会显示跳动的 until Stream.Size >= aFileSize; //直到文件大小和原文件大小一致结束循环
AThread.Connection.WriteLn('OK'); //返回一个信息 OK,让客户端知道你读完了
//释放一些文件流内存 end; Stream.Free;
//Stream:=nil;
//定义成没有人连接,准备接受下一个人的连接
State:= dstNone;
end;end.-----服务端代码结束------细心的朋友已经看出区别了吧,我改写后的代码是看着简单直接了,但是却没法多播接受文件,因为是只能接受单播(同一个时刻只能接受一个客户端的连接)的传输。所以说 ,前面的demo是先自定义了一个类 TThreadData 别小看这个类哦,其实这个类定义出来以后传播过来的文件就不会混淆,因为各自是独立的,就是说每个客户端连接过来,都会生成一个这样的类对象,作者目的是什么呢,其实就是为了让各个客户端独立起来,否则,大家都往一个服务端传文件的时候,就会所有的数据块混杂在一起了!那么我为什么要精简他呢,目的只有一个,想测试一下核心代码,因为我还要写一个精简出来的客户端,所以这个服务端就是我特意测试用来写的。-------------------ok!接下来看我精简分解出来的客户端代码
在看代码之前提醒一下,请注意,我这个IdTCPClient组件对象是动态创建的,在Button1Click事件里大家也可以看到动态创建一些对象的方法。这个是我改写的实现 传输文件的 局域网内程序。。用来做数据备份的朋友应该可以使用哦在外网如果是公网IP估计也是可以使用的记住测试的时候 要在客户端目录里 放一个大文件 test.rar 在服务端目录下就会生成一个同样的文件了,这就是传输过来生成的。这个程序只是一个demo用来讲解 idtcpclient 如何 朝 Idtcpserver 传输文件效率还有些问题,就是运行时 感觉本地机器CPU会比较高,就像复制文件一样 赫赫 如何解决这样的问题呢?如果有朋友知道的话 一起探讨一下哦!------------客户端代码--------------------
unit Unit1;interfaceuses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient,
StdCtrls;type
TForm1 = class(TForm)
Button1: TButton; procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;var
Form1: TForm1;
Buf : array[0..1023] of Byte;
aSize, ReadCount, Tmpint : Integer;
aStream : TFileStream;
aIdTCPClient: TIdTCPClient;
FFileName:string;implementation{$R *.dfm}procedure TForm1.Button1Click(Sender: TObject);
begin
FFileName:='test.rar';
aStream := nil;
aIdTCPClient := nil;
try
aStream := TFileStream.Create(FFileName, fmOpenRead or fmShareDenyWrite);
aIdTCPClient := TIdTCPClient.Create(Application);
aIdTCPClient.Port := 5432;
aIdTCPClient.Host := '127.0.0.1';
aIdTCPClient.Connect(5000);
//发送文件名
aIdTCPClient.WriteLn(ExtractFileName(FFileName));
//等待接受确认
aIdTCPClient.ReadLn(#13#10, 1000);
//写文件长度和文件流
aSize := aStream.Size;
aIdTCPClient.WriteBuffer(aSize, 4);
while aStream.Position < aStream.Size do
begin
if aStream.Size - aStream.Position >= SizeOf(Buf) then
ReadCount := sizeOf(Buf)
else ReadCount := aStream.Size - aStream.Position; aStream.ReadBuffer(Buf, ReadCount);
aIdTCPClient.WriteBuffer(Buf, ReadCount);
end;
aIdTCPClient.ReadLn;
aIdTCPClient.Disconnect; finally aIdTCPClient.Disconnect;
if aStream<>nil then FreeAndNil(aStream);
if aIdTCPClient<>nil then FreeAndNil(aIdTCPClient);
end;
end;end.