基于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的文件传输作了一个初步 ...
随机推荐
- 《从零開始学Swift》学习笔记(Day 1)——我的第一行Swift代码
Swift 2.0学习笔记--我的第一行Swift代码 原创文章,欢迎转载. 转载请注明:关东升的博客 当第一次看到以下代码时我石化了.这些代码是什么东东?单词拼出来的? import Foun ...
- GCD网络多线程---同步运行,异步运行,串行队列,并行队列
总结:同步(无论是串行还是并行)----不又一次开辟子线程 异步(无论是串行还是并行)----开辟子线程 GCD: dispatch queue 主线程的main queue 并行队列 global ...
- js实现金额小写转大写
function convertCurrency(currencyDigits) { var MAXIMUM_NUMBER = 1000000000000.00; var CN_ZERO = &quo ...
- [Javascript] Javascript 'in' opreator
If you want to check whether a key is inside an Object or Array, you can use 'in': Object: const obj ...
- python启动应用程序和终止应用程序
python启动应用程序和终止应用程序 1. 目的 每天上班,工作需要,电脑上需要每天开机启动一些软件,下班时候,需要关掉一些软件.一个一个打开和关闭貌似是很繁琐的,于是乎,这个脚本产生了. 2. 环 ...
- js进阶 10-6 jquery中的属性选择器有哪些
js进阶 10-6 jquery中的属性选择器有哪些 一.总结 一句话总结: 1.第一遍能学会么? 一遍是肯定学不会的,要多学几遍,所以想着怎么加快速度,减少学习的遍数 2.属性选择器是干嘛的? 选择 ...
- 【t077】宝物筛选
Time Limit: 1 second Memory Limit: 128 MB [问题描述] 小FF找到了王室的宝物室,里面堆满了无数价值连城的宝物--这下小FF可发财了.但是这里的宝物实在是太多 ...
- python 使用顺序表实现栈和队列
栈: # -*- coding: utf-8 -*- # @author: Tele # @Time : 2019/04/24 下午 2:33 # 采用list(顺序表)实现栈结构,后入先出 clas ...
- 带你轻松看源代码---AsyncTask(异步任务)
本文出自博客Vander丶CSDN博客,如需转载请标明出处,尊重原创谢谢 博客地址:http://blog.csdn.net/l540675759/article/details/62893318 写 ...
- 【hdu2825】ac自动机 + 状压dp
传送门 题目大意: 给你一些密码片段字符串,让你求长度为n,且至少包含k个不同密码片段串的字符串的数量. 题解: 因为密码串不多,可以考虑状态压缩 设dp[i][j][sta]表示长为i的字符串匹配到 ...