//服务端:

const
  //transmit用的参数
  TF_USE_KERNEL_APC     = $20;
  //命令类型
  CMD_CapScreen             = 2000;
  CMD_CapVideo              = 2001;
  CMD_CapAudio              = 2002;
  CMD_GetSystemInfo         = 2003;
  CMD_TransmitFiles         = 2004;
  
//通用数据传输包体封装
type
  //每个完整数据的头描述
  TPacketHeader =  packed record
     PacketCMD    : Word;   //包类型
     DataLength   : Word;   //包体长度
     IsCompressed : Boolean//包体是否为压缩数据
  end;
  TBytes = array [0..65535of Byte;
  TPacketBody = packed record
     Data : TBytes;
  end;
  //完整的数据包
  TPacketInfo = packed record
    Header : TPacketHeader;
    Body   : TPacketBody;
  end;
  //文件发送包
  TFileSendPacket = packed record
    FileName : array [0..127of Char;
    FileSize : LongWord;
    StartWritePositon : LongWord;
    hFile : THandle;
  end;
function TServerClientSocket.TransFile(FileName: string;StartWritePositon:LongWord): Boolean;
var
  hFile : THandle;
  NumberOfByteSend : LongWord;
  Block:PBlock;
  PacketInfo: TPacketInfo;
  FileSendPacket : TFileSendPacket;
  AFileName : string[128];
  TransmitFileBuffers : TTransmitFileBuffers;
begin
    if not FileExists(FileName) then
    begin
      Result := False;
      Exit;
    end;
    
    hFile := CreateFile(PChar(FileName), GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, 00);
    //如果文件打开错误,则退出
    if hFile = INVALID_HANDLE_VALUE then
    begin
      Result := False;
      Closehandle(hFile);
      Exit;
    end;
    //得到需要传输的字节数
    NumberOfByteSend := windows.GetFileSize(hFile, nil) - StartWritePositon;
    if NumberOfByteSend <= 0 then
    begin
      Closehandle(hFile);
      Exit;
    end;
    Block := AllocBlock;
    Block.Data.Event := seFileSend;
    Block.Data.Overlapped.Offset := StartWritePositon;
    AFileName := ExtractFileName(FileName);
    FillChar(PacketInfo,SizeOf(TPacketInfo),0);
    FillChar(FileSendPacket,SizeOf(TFileSendPacket),0);
    Move(AFileName[1],FileSendPacket.FileName,length(AFileName));
    FileSendPacket.FileSize := NumberOfByteSend;
    FileSendPacket.StartWritePositon := StartWritePositon;
    FileSendPacket.hFile := hFile;
    PacketInfo.Header.PacketCMD := CMD_TransmitFiles;
    PacketInfo.Header.DataLength := Sizeof(TFileSendPacket);
    PacketInfo.Header.IsCompressed := False;
    Move(FileSendPacket,PacketInfo.Body.Data,SizeOf(TFileSendPacket));
    Move(PacketInfo,Block^.Data.Buffer,SizeOf(TPacketHeader) + SizeOf(TFileSendPacket));
    //传输文件前发送的包
    TransmitFileBuffers.Head := @Block^.Data.Buffer[0];
    TransmitFileBuffers.HeadLength := SizeOf(TPacketHeader) + SizeOf(TFileSendPacket);
    //传输文件完毕后发送的包
    TransmitFileBuffers.Tail := nil;
    TransmitFileBuffers.TailLength := 0;
    LogMsg('开始发送文件:' + FileName + ' Size=' + IntToStr(NumberOfByteSend));
    //发送命令,并将文件名、继传点、需要传输的大小传递过去
    if not TransmitFile(SocketHandle, hFile, NumberOfByteSend, MAX_BUFSIZE,
      @Block^.Data.Overlapped, @TransmitFileBuffers, TF_USE_KERNEL_APC) then
    begin
      if GetLastError <> ERROR_IO_PENDING then
      begin
        Result := False;
        Exit;
      end;
    end;
    Result := True;
end;
//如果发送完毕,可以接收到重叠IO的返回结果
    case Block^.Data.Event of
      seFileSend:
      begin
        Block.IsUse := False;
        Move(Block.Data.Buffer,PacketInfo,SizeOf(TPacketHeader) + SizeOf(TFileSendPacket));
        if PacketInfo.Header.PacketCMD = CMD_TransmitFiles then
        begin
           FillChar(FileSendPacket,SizeOf(TFileSendPacket),0);
           Move(PacketInfo.body.data,FileSendPacket,SizeOf(TFileSendPacket));
           Closehandle(FileSendPacket.hFile); //发送完毕,关闭文件句柄
        end;
        LogMsg('文件:' + StrPas(FileSendPacket.FileName) + '  发送完毕!');
        if not PrepareRecv() then Result := RESPONSE_FAIL;       
      end;
      seRead: 。。。。。。。
  
//客户端:
procedure TrecvThread.Execute;
var PacketInfo : TPacketInfo;
    str: string;
    FileSendPacket:TFileSendPacket;
    FileStream:TFileStream;
    FileName :string;
    RecBuf:array[0..1023of Char;
    RemainByts,RecvedBytes:Integer;
begin
  while (not self.Terminated ) DO
  begin
    cs.CheckForDisconnect(False);
     if cs.ClosedGracefully then
     begin
        Fmm.Lines.Add('链路断开!');
        self.Terminate;
     end;
     cs.ReadBuffer(PacketInfo.Header,SizeOf(TPacketHeader));
     cs.ReadBuffer(PacketInfo.Body.Data, PacketInfo.Header.DataLength);
     if PacketInfo.Header.PacketCMD = CMD_TransmitFiles then
     begin
       Move(PacketInfo.Body.Data,FileSendPacket,PacketInfo.Header.DataLength);
       FileName := StrPas(FileSendPacket.FileName);
       try
         FileStream := TFileStream.Create('C:\'+ FileName, fmCreate or fmOpenWrite);
         Fmm.Lines.Add('接收:' + FileName + ' Size=' + IntToStr(FileSendPacket.FileSize));
         RecvedBytes := 0;
         while (RecvedBytes < FileSendPacket.FileSize) do
         begin
           if FileSendPacket.FileSize <= 1024 then
           begin
             cs.ReadBuffer(RecBuf,FileSendPacket.FileSize);
             RecvedBytes := FileSendPacket.FileSize;
             FileStream.WriteBuffer(RecBuf,RecvedBytes);
             Break;
           end else begin
             cs.ReadBuffer(RecBuf,1024);
             RecvedBytes := RecvedBytes + 1024;
             FileStream.WriteBuffer(RecBuf,1024);
             RemainByts := FileSendPacket.FileSize - RecvedBytes;
             if RemainByts <= 1024 then
             begin
               cs.ReadBuffer(RecBuf,RemainByts);
               RecvedBytes := RecvedBytes + RemainByts;
               FileStream.WriteBuffer(RecBuf,RemainByts);
               Break;
             end;
           end;
         end;
       finally
          FileStream.Free;
       end;
     end;
  end;
end;

http://www.delphi6.com/thread-554.htm

基于IOCP的高速文件传输代码的更多相关文章

  1. Tftp文件传输服务器(基于UDP协议)

    一个简单的UDP服务端与客户端 服务端: from socket import * #创建套接字 udp_server = socket(AF_INET,SOCK_DGRAM) msg_server ...

  2. WCF大文件传输服务

    由于项目需要,自己写一个基于WCF的大文件传输服务雏形.觉得有一定的参考价值,因此放在网上分享. 目前版本为v1.1特点如下: 1.文件传输端口为18650 2.上传和下载文件 3.支持获取文件传输状 ...

  3. vsftpd-基于ftp协议的文件传输服务器软件

    第一部分:在Linux上部署vsftpd服务 1. vsftpd简介 1.1 vsftpd是什么? ftp(File Transfer Protocol)文件传输协议.(实现不同操作系统之间文件的传输 ...

  4. QT从入门到入土(九)——TCP/IP网络通信(以及文件传输)

    引言 TCP/IP通信(即SOCKET通信)是通过网线将服务器Server端和客户机Client端进行连接,在遵循ISO/OSI模型的四层层级构架的基础上通过TCP/IP协议建立的通讯.控制器可以设置 ...

  5. Python之路(第三十二篇) 网络编程:udp套接字、简单文件传输

    一.UDP套接字 服务端 # udp是无链接的,先启动哪一端都不会报错 # udp没有链接,与tcp相比没有链接循环,只有通讯循环 server = socket.socket(socket.AF_I ...

  6. Python实现终端FTP文件传输

    实现终端FTP文件传输 代码结构: .├── client.py├── readme.txt└── server.py 运行截图: readme.txt tftp文件服务器 项目功能: * 客户端有简 ...

  7. Python自带HTTP文件传输服务

    一行命令搭建一个基于python的http文件传输服务 由于今天朋友想要一个文件,而我恰好有,因为这个文件比较大,网速不是很给力,所以想到了python自己有这么一个功能,这样不仅不需要下载其他软件, ...

  8. Java基于Socket文件传输示例(转)

    最近需要进行网络传输大文件,于是对基于socket的文件传输作了一个初步的了解.在一位网友提供的程序基础上,俺进行了一些加工,采用了缓冲输入/输出流来包装输出流,再采用数据输入/输出输出流进行包装,加 ...

  9. Java基于Socket文件传输示例

    http://www.blogjava.net/sterning/archive/2007/10/13/152508.html 最近需要进行网络传输大文件,于是对基于socket的文件传输作了一个初步 ...

随机推荐

  1. Java CPU使用率过高分析

    http://note.youdao.com/publicshare/?id=d02cba2714709d4d4fe8a8627fc1cf41&type=note#/ (友情提示:本博文章欢迎 ...

  2. HTML Email 编写指南(转)

      作者: 阮一峰 日期: 2013年6月16日 今天,我想写一个"低技术"问题. 话说我订阅了不少了新闻邮件(Newsletter),比如JavaScript Weekly.每周 ...

  3. Android使用JNI实现Java与C之间传递数据

    介绍Java如何将数据传递给C和C回调Java的方法. java传递数据给C,在C代码中进行处理数据,处理完数据后返回给java.C的回调是Java传递数据给C,C需要用到Java中的某个方法,就需要 ...

  4. 简体和繁体加起来有六七万个汉字,所以Unicode只能排除一些几乎不用的汉字,Unicode编码的熟悉与研究过程(内附全部汉字编码列表)

    我有一个问题是:是不是会有个别汉字无法在Unicode下表示,这种情况下就不能完全显示了? 各种编码查询表:http://bm.kdd.cc/ ---------------------------- ...

  5. NOIP2016 天天爱跑步 - 树上差分

    传送门 题目分析: 一年前还是个傻子的时候居然直接放弃了这题. 首先列出两个方程:如果i节点的观察员能够观察到由s->t的那个人,那么: \[dep[s] - dep[i] = w[i], de ...

  6. RGB 的调色

    通过 RGB 三通道所占比的组合(通过三元素长的元组存储),可呈现丰富的色彩样式: [0, 0, 0] ⇒ 黑色,[1, 1, 1] ⇒ 白色 [1, 0, 0] ⇒ 红色,[0, 1, 0] ⇒ 绿 ...

  7. Android菜鸟的成长笔记(24)——Android中的振动器

    在某些时候,程序需要启动系统振动器,比如手机静音时使用振动提示用户:再比如玩游戏时,当系统碰撞.爆炸时使用振动带给用户更逼真的体验等.总之,振动是除视频.声音之外的另一种"多媒体" ...

  8. JAVA SE回顾及思考(3)——排序算法

    排序的算法是很多公司的笔试和面试题,个人感觉Java中其实无需使用这些排序方法,因为Java中已经为我们提供了很方便效率很高的sort()方法.但是不使用不能代表不需要学习这些算法,也不是仅仅为了面试 ...

  9. react持续记录零散笔记

    根据 React 的设计,所有的 DOM 变动,都先在虚拟 DOM 上发生,然后再将实际发生变动的部分,反映在真实 DOM上,这种算法叫做 DOM diff 这些生命周期在深入项目开发阶段是非常重要的 ...

  10. 使用相对路径导入ado库的方法

    作者:朱金灿 来源:http://blog.csdn.net/clever101 常用的导入ado库的语句: #import "c:\program files\common files\s ...