基于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的文件传输作了一个初步 ...
随机推荐
- 利用C#与AE调用GP工具
转自原文 利用C#与AE调用GP工具 第一,首先要明确自己需要调用arctoolbox里面的什么工具,实现什么样的功能. 第三,编写command或tool工具,编写自己要的功能工具. 1)首先创建一 ...
- MySQL参数文件位置
对于linux/unix: mysql --help|grep my.cnf /etc/my.cnf, /etc/mysql/my.cnf, /usr/local/etc/my.cnf, ~/.m ...
- 【前端统计图】echarts实现单条折线图
五分钟上手: 图片.png <!DOCTYPE html> <html> <head> <meta charset="utf-8"> ...
- 于 Android NDK 的学习之旅-----数据传输(基本数据类型和数组传输)
之前的一些文章都有涉及到上层和中间层的数据传输,简单来说,也就是参数和返回值的使用.因为中间层要做的最多的也就是数据传输与转换,下面来介绍下这方面的知识. 数据传输可分为 基本数据类型传输 和 引用数 ...
- 常用binlog日志操作命令
1.查看所有binlog日志列表 mysql> show master logs; 2.查看master状态,即最后(最新)一个binlog日志的编号名称,及其最后一个操作事件pos结束点(Po ...
- Java实现的并发任务处理实例
本文实例讲述了Java实现的并发任务处理方法.分享给大家供大家参考,具体如下: public void init() { super.init(); this.ioThreadPool = new T ...
- 中国象棋V2:Java源代码、毕业设计等所有文档,已经全部提交到CSDN-Code平台
下载地址:https://code.csdn.net/FansUnion/chinesechess-v2 主要内容:Java源代码.毕业设计.API文档.声音图片等资源.Demo截图等一切的一切. 2 ...
- Java 出现内存溢出的定位以及解决方案
在上一节中Java虚拟机内存分布 说了Java虚拟机中分为五个区域,而且也知道了在Java程序计数器区域不会出现OOM(OutOfMemeryError),那么以下就对除了程序计数器以外的四个区域 ...
- 判断navigation中父控制器类型
for (UIViewController *controller in self.navigationController.viewControllers) { if ([controller is ...
- SystemServer概述
SystemServer由Zygote fork生成的,进程名为system_server,该进程承载着framework的核心服务. 调用流程如下: 上图前4步骤(即颜色为紫色的流程)运行在是Zyg ...