基于IOCP的高速文件传输代码
//服务端:
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..65535] of Byte; TPacketBody = packed record Data : TBytes; end; //完整的数据包 TPacketInfo = packed record Header : TPacketHeader; Body : TPacketBody; end; //文件发送包 TFileSendPacket = packed record FileName : array [0..127] of 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, 0, 0); //如果文件打开错误,则退出 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..1023] of 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的高速文件传输代码的更多相关文章
- Tftp文件传输服务器(基于UDP协议)
一个简单的UDP服务端与客户端 服务端: from socket import * #创建套接字 udp_server = socket(AF_INET,SOCK_DGRAM) msg_server ...
- WCF大文件传输服务
由于项目需要,自己写一个基于WCF的大文件传输服务雏形.觉得有一定的参考价值,因此放在网上分享. 目前版本为v1.1特点如下: 1.文件传输端口为18650 2.上传和下载文件 3.支持获取文件传输状 ...
- vsftpd-基于ftp协议的文件传输服务器软件
第一部分:在Linux上部署vsftpd服务 1. vsftpd简介 1.1 vsftpd是什么? ftp(File Transfer Protocol)文件传输协议.(实现不同操作系统之间文件的传输 ...
- QT从入门到入土(九)——TCP/IP网络通信(以及文件传输)
引言 TCP/IP通信(即SOCKET通信)是通过网线将服务器Server端和客户机Client端进行连接,在遵循ISO/OSI模型的四层层级构架的基础上通过TCP/IP协议建立的通讯.控制器可以设置 ...
- Python之路(第三十二篇) 网络编程:udp套接字、简单文件传输
一.UDP套接字 服务端 # udp是无链接的,先启动哪一端都不会报错 # udp没有链接,与tcp相比没有链接循环,只有通讯循环 server = socket.socket(socket.AF_I ...
- Python实现终端FTP文件传输
实现终端FTP文件传输 代码结构: .├── client.py├── readme.txt└── server.py 运行截图: readme.txt tftp文件服务器 项目功能: * 客户端有简 ...
- Python自带HTTP文件传输服务
一行命令搭建一个基于python的http文件传输服务 由于今天朋友想要一个文件,而我恰好有,因为这个文件比较大,网速不是很给力,所以想到了python自己有这么一个功能,这样不仅不需要下载其他软件, ...
- Java基于Socket文件传输示例(转)
最近需要进行网络传输大文件,于是对基于socket的文件传输作了一个初步的了解.在一位网友提供的程序基础上,俺进行了一些加工,采用了缓冲输入/输出流来包装输出流,再采用数据输入/输出输出流进行包装,加 ...
- Java基于Socket文件传输示例
http://www.blogjava.net/sterning/archive/2007/10/13/152508.html 最近需要进行网络传输大文件,于是对基于socket的文件传输作了一个初步 ...
随机推荐
- Java CPU使用率过高分析
http://note.youdao.com/publicshare/?id=d02cba2714709d4d4fe8a8627fc1cf41&type=note#/ (友情提示:本博文章欢迎 ...
- HTML Email 编写指南(转)
作者: 阮一峰 日期: 2013年6月16日 今天,我想写一个"低技术"问题. 话说我订阅了不少了新闻邮件(Newsletter),比如JavaScript Weekly.每周 ...
- Android使用JNI实现Java与C之间传递数据
介绍Java如何将数据传递给C和C回调Java的方法. java传递数据给C,在C代码中进行处理数据,处理完数据后返回给java.C的回调是Java传递数据给C,C需要用到Java中的某个方法,就需要 ...
- 简体和繁体加起来有六七万个汉字,所以Unicode只能排除一些几乎不用的汉字,Unicode编码的熟悉与研究过程(内附全部汉字编码列表)
我有一个问题是:是不是会有个别汉字无法在Unicode下表示,这种情况下就不能完全显示了? 各种编码查询表:http://bm.kdd.cc/ ---------------------------- ...
- NOIP2016 天天爱跑步 - 树上差分
传送门 题目分析: 一年前还是个傻子的时候居然直接放弃了这题. 首先列出两个方程:如果i节点的观察员能够观察到由s->t的那个人,那么: \[dep[s] - dep[i] = w[i], de ...
- RGB 的调色
通过 RGB 三通道所占比的组合(通过三元素长的元组存储),可呈现丰富的色彩样式: [0, 0, 0] ⇒ 黑色,[1, 1, 1] ⇒ 白色 [1, 0, 0] ⇒ 红色,[0, 1, 0] ⇒ 绿 ...
- Android菜鸟的成长笔记(24)——Android中的振动器
在某些时候,程序需要启动系统振动器,比如手机静音时使用振动提示用户:再比如玩游戏时,当系统碰撞.爆炸时使用振动带给用户更逼真的体验等.总之,振动是除视频.声音之外的另一种"多媒体" ...
- JAVA SE回顾及思考(3)——排序算法
排序的算法是很多公司的笔试和面试题,个人感觉Java中其实无需使用这些排序方法,因为Java中已经为我们提供了很方便效率很高的sort()方法.但是不使用不能代表不需要学习这些算法,也不是仅仅为了面试 ...
- react持续记录零散笔记
根据 React 的设计,所有的 DOM 变动,都先在虚拟 DOM 上发生,然后再将实际发生变动的部分,反映在真实 DOM上,这种算法叫做 DOM diff 这些生命周期在深入项目开发阶段是非常重要的 ...
- 使用相对路径导入ado库的方法
作者:朱金灿 来源:http://blog.csdn.net/clever101 常用的导入ado库的语句: #import "c:\program files\common files\s ...