📄 filetransmitunit.pas
字号:
ActuallySentSizePerPakage, FileRecvNotifyEvent) = SOCKET_ERROR then
begin
sleep(20);
Continue;
end
else
begin
ZeroMemory(@FileName[0], sizeof(FileName));
//再接收文件名 //在此处,扩展命令长度标识的是文件名长度
if RecvAllData(FileTransmitSocket, @FileName[0], myInterChangeHeader.ExdSource,
ActuallySentSizePerPakage, FileRecvNotifyEvent) = SOCKET_ERROR then
begin
sleep(20);
Continue;
end;
case myInterChangeHeader.Order of
RecvFile:
NeedRecvFileName := FileName;
SendFile:
begin
NeedSendFileName := FileName;
while not PostThreadMessage(RecvFileProcessTreadID, TerminateNotifyMessage,
//将断点继传点发过去
NotifySendFileData, myInterChangeHeader.OrderExtend) do
Sleep(10);
//跳出
Continue;
end;
//文件夹传输的时候,需要使用这个先创建一个dir
CreateDir:
begin
MakeDirPath := FileName;
CreateDirectory(PChar(MakeDirPath), nil);
//跳出
Continue;
end;
//发送指定文件下的所有文件列表
SendDirFileList:
begin
DirFileList := FileName;
//列出文件夹下的所有文件,并发送给sever
GetListAndSend(FileTransmitSocket, DirFileList, True, FileListTypeDir);
//跳出
Continue;
end;
end;
end;// end elseif
//再接收真正的数据
if RecvMyFile(FileTransmitSocket, NeedRecvFileName, @FileDataBuffer[0],
myDataHeaderInfo.CompressedDataSize - sizeof(myInterChangeHeader) - myInterChangeHeader.ExdSource,
//描述了断点继传点
myInterChangeHeader.OrderExtend, FileRecvNotifyEvent) = SOCKET_ERROR then
begin
sleep(20);
Continue;
end;
end;
end;
//发送文件
procedure TFileTransmit.SendFileProcess;
var
Msg : TMsg;
begin
//创建一个消息队列
PeekMessage(Msg, 0, $400, $400, PM_NOREMOVE);
Sleep(5);
while true do
begin
//接收发来的线程消息
if (PeekMessage(Msg, 0, TerminateNotifyMessage, TerminateNotifyMessage, PM_REMOVE)) then
begin
case Msg.wParam of
NotifySendFileData:
begin
//发送文件
if SendMyFile(FileTransmitSocket, NeedSendFileName, Msg.lParam) = SOCKET_ERROR then
begin
sleep(20);
Continue;
end;
end;
NotifyTermiateTransmitThread:
begin
//通知发送者,线程结束
SetEvent(MsgFileThreadNotifyEvent);
Break;
end;
end;
end
else
Sleep(1000);
end;
end;
(*---------------------------------文件收发部分-------------------------------*)
//文件的接收
function TFileTransmit.RecvMyFile(const Socket : TSocket;
const FileName : string; PakageDataRecvBuffer : Pointer;
const PakageLengthToRecv : LongInt; const StartWritePositon : LongInt = 0;
const RecvNotifyEvent : THandle = 0) : integer;
var
ErrorCode : LongInt;
TotalRecv : LongInt;
RecvBytePerRecv, BytesLeft : LongInt;
NumberOfByteWritten : DWORD;
hFile : THandle;
begin
TotalRecv := 0;
BytesLeft := PakageLengthToRecv;
RecvBytePerRecv := 0;
hFile := CreateFile(PChar(FileName), GENERIC_WRITE, FILE_SHARE_WRITE,
nil, OPEN_ALWAYS, 0, 0);
//如果文件打开或者创建错误,则退出
if hFile = INVALID_HANDLE_VALUE then
begin
Result := SOCKET_ERROR; //文件操作失败
Closehandle(hFile);
Exit;
end;
SetFilePointer(hFile, StartWritePositon, nil, FILE_BEGIN);
//循环接收文件
while (TotalRecv < PakageLengthToRecv) do
begin
RecvBytePerRecv := Recv(Socket, PakageDataRecvBuffer^, BytesLeft, 0);
if RecvBytePerRecv = SOCKET_ERROR then
begin
ErrorCode := WSAGetLastError;
if ErrorCode = WSAEWOULDBLOCK then
begin
if RecvNotifyEvent = 0 then
Sleep(1)
else
WaitForSingleObject(RecvNotifyEvent, 1);
Continue;
end
else
Break;
end;
//写入文件
WriteFile(hFile, PakageDataRecvBuffer, RecvBytePerRecv, NumberOfByteWritten, nil);
//下移文件指针
SetFilePointer(hFile, RecvBytePerRecv, nil, FILE_CURRENT);
TotalRecv := TotalRecv + RecvBytePerRecv;
BytesLeft := BytesLeft - RecvBytePerRecv;
end;
Result := Min(RecvBytePerRecv, 0);
Closehandle(hFile);
end;
//文件的发送
function TFileTransmit.SendMyFile(const Socket : TSocket; const FileName : string;
const StartWritePositon : LongInt = 0) : integer;
var
NumberOfByteSend : LongInt;
hFile, hFileMapping : THandle;
MapPointer : Pointer;
begin
Result := 0;
hFile := CreateFile(PChar(FileName), GENERIC_READ, FILE_SHARE_READ,
nil, OPEN_EXISTING, 0, 0);
//如果文件打开错误,则退出
if hFile = INVALID_HANDLE_VALUE then
begin
Result := SOCKET_ERROR; //文件操作失败
Closehandle(hFile);
Exit;
end;
NumberOfByteSend := GetFileSize(hFile, nil);
hFileMapping := CreateFileMapping(hFile, nil, PAGE_READONLY, 0, NumberOfByteSend, nil);
if hFileMapping = 0 then
begin
Result := SOCKET_ERROR; //操作失败
Closehandle(hFile);
Exit;
end;
//关闭文件句柄
Closehandle(hFile);
NumberOfByteSend := NumberOfByteSend - StartWritePositon;
MapPointer := MapViewOfFile(hFileMapping, FILE_MAP_ALL_ACCESS, 0,
StartWritePositon, NumberOfByteSend);
if MapPointer = nil then
begin
Result := SOCKET_ERROR; //操作失败
Exit;
end;
SendAllTheData(Socket, MapPointer, NumberOfByteSend, 0, FileSendNotifyEvent);
UnmapViewOfFile(MapPointer);
end;
{
//文件的发送
function TFileTransmit.SendMyFile(const Socket : TSocket; const FileName : string;
const StartWritePositon : LongInt = 0) : integer;
var
ErrorCode : LongInt;
NumberOfByteSend : LongInt;
TransmiteBuffers : TTransmitFileBuffers;
myDataHeaderInfo : TDataHeaderInfo;
hFile : THandle;
begin
Result := 0;
hFile := CreateFile(PChar(FileName), GENERIC_READ, FILE_SHARE_READ,
nil, OPEN_EXISTING, 0, 0);
//如果文件打开错误,则退出
if hFile = INVALID_HANDLE_VALUE then
begin
Result := SOCKET_ERROR; //文件操作失败
Closehandle(hFile);
Exit;
end;
//移动文件指针到继传点
NumberOfByteSend := GetFileSize(hFile, nil);
SetFilePointer(hFile, StartWritePositon, nil, FILE_BEGIN);
NumberOfByteSend := NumberOfByteSend - StartWritePositon;
ZeroMemory(@TransmiteBuffers, sizeof(TransmiteBuffers));
//发送的数据头
myDataHeaderInfo.UnCompressedDataSize := 0;
myDataHeaderInfo.CompressedDataSize := NumberOfByteSend;
TransmiteBuffers.Head := @myDataHeaderInfo;
TransmiteBuffers.HeadLength := sizeof(myDataHeaderInfo);
//发送数据
if not TransmitFile(Socket, hFile, NumberOfByteSend, DATA_BUFSIZE, nil,
@TransmiteBuffers, TF_USE_KERNEL_APC) then
begin
ErrorCode := WSAGetLastError;
//MSDN说明,在overlapped结构不是nil的,才返回这个的,会不会有问题?这里============
if (ErrorCode = ERROR_IO_PENDING) or (ErrorCode = WSA_IO_PENDING) then
begin
WaitForSingleObject(Socket, INFINITE);
end
else
Result := SOCKET_ERROR;
end;
Closehandle(hFile);
end;
}
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -