热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

利用Delphi中的IdTCPServer和IdTCPClient实现高效文件传输

本文介绍了如何利用Delphi中的IdTCPServer和IdTCPClient控件实现高效的文件传输。这些控件在默认情况下采用阻塞模式,并且服务器端已经集成了多线程处理,能够支持任意大小的文件传输,无需担心数据包大小的限制。与传统的ClientSocket相比,Indy控件提供了更为简洁和可靠的解决方案,特别适用于开发高性能的网络文件传输应用程序。

其它某些文件传输代码精练很多,传输的文件大小任意,个人建议:写网络文件传输程序时最好用Indy的控件(因为其默认即阻塞模式,Server端已封装了多线程,没有数据包大小限制),ClientSocket VS ServerSocket传输文件很麻烦,要自定通信协议,并且有个8KB的瓶颈,实现大文件传输比较麻烦,

服务端发送:
var
    iFileHandle:integer;
    iFileLen,cnt:integer;
    buf:array[0..4096] of byte;
begin
    iFileHandle:=FileOpen('E:\Study\深入Delphi6网络编程.rar',fmOpenRead);
    iFileLen:=FileSeek(iFileHandle,0,2);
    FileSeek(iFileHandle,0,0);
    AThread.Connection.WriteInteger(iFileLen);
    while true do
    begin
        cnt:=FileRead(iFileHandle,buf,4096);
        AThread.Connection.WriteBuffer(buf,cnt);
        if cnt<4096 then
            break;
    end;
    FileClose(iFileHandle);
end;

=======================================================

客户端接收:
procedure TForm1.Button1Click(Sender: TObject);
var
    rbyte:array[0..4096] of byte;
    sFile:TFileStream;
    iFileSize:integer;
begin
    try
        IdTcpClient1.Connect(5000);
    except
        exit;
    end;

    iFileSize:=IdTCPClient1.ReadInteger;

    sFile:=TFileStream.Create('e:\bb.tmp',fmCreate);
    While iFileSize>4096 do
    begin
        IdTCPClient1.ReadBuffer(rbyte,4096);// .ReadBuffer(rbyte,iLen);
        sFile.Write(rByte,4096);
        inc(iFileSize,-4096);
    end;
    IdTCPClient1.ReadBuffer(rbyte,iFileSize);// .ReadBuffer(rbyte,iLen);
    sFile.Write(rByte,iFileSize);
    sFile.Free;
    ShowMessage('file get ok!');
end;

 

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

具体代码:

Server(Receive):

procedure TFrmServer.FormCreate(Sender: TObject);
begin
   IdTCPServer1.DefaultPort:=5616;
   IdTCPServer1.Active:=True;
end;

procedure TFrmServer.IdTCPServer1Execute(AThread: TIdPeerThread);
var
    rbyte:array[0..4096] of byte;
    sFile:TFileStream;
    cnt,cmd,FileSize:integer;
    str,FileName:string;

begin
    str:=AThread.Connection.ReadLn;   //接收文件大小及文件名
    cmd:=pos('|',str); //查找分隔符
    FileName:=copy(str,1,cmd-1); //提取文件名
    FileSize:=StrToInt(copy(str,cmd+1,Length(str)-cmd+1)); //提取文件大小
    if MessageBox(0,Pchar('用户 '+AThread.Connection.Socket.Binding.PeerIP+'要给您传送文件 "'+FileName+'" 您是接受还是拒绝?'),'文件接受',MB_YesNo or MB_ICONQUESTION)=ID_Yes then //询问是否接收
    begin
      ProgressBar1.Max:=FileSize;   //初始化进度条
      ProgressBar1.Position:=0;
      SaveDialog1.FileName:=FileName; //指定保存的默认文件名,一定要在 SaveDialog1.Execute;之前,不然文件名为空
      SaveDialog1.Execute;
      sFile:=TFileStream.Create(SaveDialog1.FileName,fmCreate); //创建待写入的文件流
      While FileSize>4096 do
      begin
        AThread.Connection.ReadBuffer(rbyte,4096);// 读取文件流
        sFile.Write(rByte,4096);      //写入文件流
        cnt:=AThread.Connection.ReadInteger; //从发送端接收最新的进度位置信息
        ProgressBar1.Position:=ProgressBar1.Position+cnt; //更新显示进度
        Label1.Caption:='当前接收进度..';
        StatusBar1.Panels[0].Text:='正在接收文件中...';
        inc(FileSize,-4096);
     end;
    AThread.Connection.ReadBuffer(rbyte,FileSize);// .ReadBuffer(rbyte,iLen);
    sFile.Write(rByte,FileSize);
    sFile.Free;
    StatusBar1.Panels[0].Text:='文件接收完成!';
    Label1.Caption:='文件接收完成!';
    end;
   END;

procedure TFrmServer.FormDestroy(Sender: TObject);
begin
   IdTCPServer1.Active:=False;
   Application.Terminate;
end;

Client(Send):

procedure TFrmClient.SpeedButton1Click(Sender: TObject);
begin
   OpenDialog1.Execute;
   edtFileName.Text:=OpenDialog1.FileName;
end;

procedure TFrmClient.btnSendClick(Sender: TObject);
var
    iFileHandle:integer;
    iFileLen,cnt:integer;
    buf:array[0..4096] of byte;

begin
if (edtAddress.Text<>'')and (edtFileName.Text<>'') then
begin
    IdTCPClient1.Host:=edtAddress.Text;
    IdTCPClient1.Port:=5616;
    try
      IdTCPClient1.Connect(5000);
    except
      StatusBar1.Panels[0].Text:='连接接受方失败!';
      exit;
    end;
    if IdTCPClient1.Connected then
    begin
      iFileHandle:=FileOpen(edtFileName.Text,fmOpenRead);
      iFileLen:=FileSeek(iFileHandle,0,2);
      FileSeek(iFileHandle,0,0);
      ProgressBar1.Max:=iFileLen;
      ProgressBar1.Position := 0;
      IdTCPClient1.WriteLn(ExtractFileName(edtFileName.Text)+'|'+IntToStr(iFileLen));
      while true do
      begin
        Application.ProcessMessages;
        cnt:=FileRead(iFileHandle,buf,4096);
        IdTCPClient1.WriteBuffer(buf,cnt);
        IdTCPClient1.WriteInteger(cnt);
        ProgressBar1.Position:=ProgressBar1.Position + cnt;
        StatusBar1.Panels[0].Text:='正在传送文件...';
        if cnt<4096 then
            break;
      end;
      FileClose(iFileHandle);
      Label2.Caption:='文件传送完成!';
      StatusBar1.Panels[0].Text:='文件传送完成!';
     end;
end
else
    ShowMessage('请选择要传送的文件和或接受方地址');
end;


推荐阅读
  • 深入理解Redis的数据结构与对象系统
    本文详细探讨了Redis中的数据结构和对象系统的实现,包括字符串、列表、集合、哈希表和有序集合等五种核心对象类型,以及它们所使用的底层数据结构。通过分析源码和相关文献,帮助读者更好地理解Redis的设计原理。 ... [详细]
  • UNP 第9章:主机名与地址转换
    本章探讨了用于在主机名和数值地址之间进行转换的函数,如gethostbyname和gethostbyaddr。此外,还介绍了getservbyname和getservbyport函数,用于在服务器名和端口号之间进行转换。 ... [详细]
  • 20100423:Fixes:更新批处理,以兼容WIN7。第一次系统地玩QT,于是诞生了此预备式:【QT版本4.6.0&#x ... [详细]
  • 本文深入探讨了HTTP请求和响应对象的使用,详细介绍了如何通过响应对象向客户端发送数据、处理中文乱码问题以及常见的HTTP状态码。此外,还涵盖了文件下载、请求重定向、请求转发等高级功能。 ... [详细]
  • 优化ListView性能
    本文深入探讨了如何通过多种技术手段优化ListView的性能,包括视图复用、ViewHolder模式、分批加载数据、图片优化及内存管理等。这些方法能够显著提升应用的响应速度和用户体验。 ... [详细]
  • Windows服务与数据库交互问题解析
    本文探讨了在Windows 10(64位)环境下开发的Windows服务,旨在定期向本地MS SQL Server (v.11)插入记录。尽管服务已成功安装并运行,但记录并未正确插入。我们将详细分析可能的原因及解决方案。 ... [详细]
  • 本文详细介绍了 GWT 中 PopupPanel 类的 onKeyDownPreview 方法,提供了多个代码示例及应用场景,帮助开发者更好地理解和使用该方法。 ... [详细]
  • 本文介绍如何使用Objective-C结合dispatch库进行并发编程,以提高素数计数任务的效率。通过对比纯C代码与引入并发机制后的代码,展示dispatch库的强大功能。 ... [详细]
  • 深入理解 SQL 视图、存储过程与事务
    本文详细介绍了SQL中的视图、存储过程和事务的概念及应用。视图为用户提供了一种灵活的数据查询方式,存储过程则封装了复杂的SQL逻辑,而事务确保了数据库操作的完整性和一致性。 ... [详细]
  • 深入解析Spring Cloud Ribbon负载均衡机制
    本文详细介绍了Spring Cloud中的Ribbon组件如何实现服务调用的负载均衡。通过分析其工作原理、源码结构及配置方式,帮助读者理解Ribbon在分布式系统中的重要作用。 ... [详细]
  • DNN Community 和 Professional 版本的主要差异
    本文详细解析了 DotNetNuke (DNN) 的两种主要版本:Community 和 Professional。通过对比两者的功能和附加组件,帮助用户选择最适合其需求的版本。 ... [详细]
  • MQTT技术周报:硬件连接与协议解析
    本周开发笔记重点介绍了在新项目中使用MQTT协议进行硬件连接的技术细节,涵盖其特性、原理及实现步骤。 ... [详细]
  • 本文详细介绍如何使用Samba软件配置CIFS文件共享服务,涵盖安装、配置、权限管理及多用户挂载等关键步骤。通过具体示例和命令行操作,帮助读者快速搭建并优化Samba服务器。 ... [详细]
  • 本教程涵盖OpenGL基础操作及直线光栅化技术,包括点的绘制、简单图形绘制、直线绘制以及DDA和中点画线算法。通过逐步实践,帮助读者掌握OpenGL的基本使用方法。 ... [详细]
  • 解决JAX-WS动态客户端工厂弃用问题并迁移到XFire
    在处理Java项目中的JAR包冲突时,我们遇到了JaxWsDynamicClientFactory被弃用的问题,并成功将其迁移到org.codehaus.xfire.client。本文详细介绍了这一过程及解决方案。 ... [详细]
author-avatar
东儿2502858537
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有