赞
踩
delphi 自带的TIdFtpServer和TIdFtpClient组件,在实际应用中发现,只能单线程传输较小的文件。有很大局限性。决定自己写一个文件传输系统。该传输系统经测试,可以同时传输100个文件以上,超过4G大小的文件,支持断点续传。同时支持对文件夹的压缩传输。基本满足业务的要求。现在把服务器端和客户端代码粘贴如下:
一、客户端
1、传输单元
- unit uTransFileClient;
-
- interface
- uses windows,graphics,classes,zip,uSocket,uStr,uConfig;
- const
- MAXPATH=260;
- MAXBUF=8192;
- CMD_FILE_LIST=4001;//列举目录;传递绝对路径;
- CMD_FILE_TRANS=4002;//文件传输
- CMD_FILE_DEL=4003;//删除文件
-
- wm_user=$0400;
- wm_TransData=wm_user+100+1;
- type
-
- TAPIFlag=(Fstart,Frecv,Fsend,Fend);
- TThreadType=(FListFile,FTransFile);
-
- pTransFilesInfo=^stTransFilesInfo;
- stTransFilesInfo=packed record
- server:stSvrAddr;
- clientFile:array[0..MAX_PATH-1] of ansiChar;
- serverFile:array[0..MAX_PATH-1] of ansiChar;
- bUpLoad:bool;
- bFolder:bool;
- bCompleteDel:bool;
- aAPI:TAPIFlag;
- transed:cardinal;
- FileSize:cardinal;
- threadId:integer;
- end;
- pRequestFileInfo=^stRequestFileInfo;
- stRequestFileInfo=packed record
- fileName:array[0..MAX_PATH-1] of ansiChar;
- bUpLoad:bool;
- end;//
- pRecvData=^stRecvData;
- stRecvData=packed record
- server:stSvrAddr;
- data:pointer;
- dataSize:integer;
- end;
- pListFile=^stListFile;
- stListFile=packed record
- server:stSvrAddr;
- filename:array[0..MAX_PATH-1] of ansiChar;
- data:pointer;
- dataSize:integer;
- end;
-
- function TransFilesClientThread(pTransFilesPara:pointer):BOOL;stdcall;
- function TransFileClientThread(pTransFilePara:pointer):bool;stdcall;
- procedure ProcessTransFile(const LocalFilename,RemoteFilename:ansiString;bUpload:boolean);overload;
- procedure ProcessTransFile(const LocalFilename,RemoteFilename:ansiString;bUpload:boolean;threadId:integer);overload;
- procedure initAddr();
- procedure uploadFile(const LocalFilename,RemoteFilename:ansiString);
- procedure downloadFile(const LocalFilename,RemoteFilename:ansiString);overload;
- procedure downloadFile(const LocalFilename,RemoteFilename:ansiString;threadId:integer);overload;
- function ListFileThread():bool;stdcall;
- procedure ProcessListFile();
- var
- DataSvrAddr:stSvrAddr;
- gFileList:ansiString;
- hForm:THANDLE;
- implementation
-
- procedure ProcessListFile();
- var
- hd,id:cardinal;
- begin
- gFileList:='';
- hd:=createthread(nil,0,@ListFileThread,nil,0,id);
- closehandle(hd);
- end;
- function ListFileThread():bool;stdcall;
- var
- hSocket:integer;
- oh:stOrderHeader;
- begin
- result:=false;
- try
- if not ConnectServer(hSocket,DataSvrAddr) then exit;
- formatOH(oh);oh.cmd:=CMD_FILE_LIST;
- SendBuf(hSocket,@oh,sizeof(oh));
- //SendBuf(hSocket,@pList^.filename[0],MAX_PATH);
- if not RecvBuf(hSocket,@oh,sizeof(oh)) then exit;
- if(oh.len<=0)then exit;
- setlength(gFileList,oh.len);
- if not RecvBuf(hSocket,@gFileList[1],oh.len) then exit;
- finally
- SendMessage(hform,wm_TransData,integer(FListFile),0);
- FreeSocket(hSocket);
- end;
- end;
-
- procedure uploadFile(const LocalFilename,RemoteFilename:ansiString);
- begin
- ProcessTransFile(LocalFilename,RemoteFilename,true);
- end;
- procedure downloadFile(const LocalFilename,RemoteFilename:ansiString);
- var
- uploadfile:string;
- begin
- uploadfile:='\upload\'+RemoteFilename;
- ProcessTransFile(LocalFilename,uploadfile,false);
- end;
- procedure downloadFile(const LocalFilename,RemoteFilename:ansiString;threadId:integer);
- var
- uploadfile:string;
- begin
- uploadfile:='\upload\'+RemoteFilename;
- ProcessTransFile(LocalFilename,uploadfile,false,threadId);
- end;
- procedure ProcessTransFile(const LocalFilename,RemoteFilename:ansiString;bUpload:boolean;threadId:integer);
- var
- pTF:pTransFilesInfo;
- hd,id:cardinal;
- begin
- new(pTF);
- zeromemory(pTF,sizeof(stTransFilesInfo));
- strcopy(pTF^.clientFile,pansichar(LocalFilename));
- strcopy(pTF^.serverFile,pansichar(RemoteFilename));
- pTF^.bUpLoad:=bUpload;
- pTF^.bFolder:=false;
- pTF^.bCompleteDel:=false;
- pTF^.server:=DataSvrAddr;
- pTF^.threadId:=threadId;
- hd:=createthread(nil,0,@TransFilesClientThread,pTF,0,id);
- closehandle(hd);
- end;
- procedure ProcessTransFile(const LocalFilename,RemoteFilename:ansiString;bUpload:boolean);
- var
- pTF:pTransFilesInfo;
- hd,id:cardinal;
- begin
- new(pTF);
- zeromemory(pTF,sizeof(stTransFilesInfo));
- strcopy(pTF^.clientFile,pansichar(LocalFilename));
- strcopy(pTF^.serverFile,pansichar(RemoteFilename));
- pTF^.bUpLoad:=bUpload;
- pTF^.bFolder:=false;
- pTF^.bCompleteDel:=false;
- pTF^.server:=DataSvrAddr;
-
- hd:=createthread(nil,0,@TransFilesClientThread,pTF,0,id);
- closehandle(hd);
- end;
- function TransFileClientThread(pTransFilePara:pointer):bool;stdcall;
- label 1;
- var
- pTransFileInfo:pTransFilesInfo;
- hSocket:integer;
- hFile,FileSize,NumberOfRead,srvFileSize,wLen,fileSizeHigh,srvFileSizeHigh:cardinal;
- err,recvLen:integer;
- buf:array[0..MAXBUF-1] of ansiChar;
- RequestFileInfo:stRequestFileInfo;
- bRet:LongBool;
- bTransType:byte;
- dwAccess,dwCreation,dwAtrr,dwShare:DWORD;
- oh:stOrderHeader;
- begin
- result:=false;
- pTransFileInfo:=pTransFilePara;
- if pTransFileInfo^.bUpLoad then
- begin
- dwAccess:=GENERIC_READ;
- dwCreation:=OPEN_EXISTING;
- dwAtrr:=FILE_ATTRIBUTE_NORMAL;
- dwShare:=FILE_SHARE_READ;
- end
- else begin
- dwAccess:=GENERIC_READ or GENERIC_WRITE;
- dwCreation:=OPEN_ALWAYS;
- dwAtrr:=FILE_ATTRIBUTE_NORMAL or FILE_ATTRIBUTE_ARCHIVE;
- dwShare:=FILE_SHARE_DELETE or FILE_SHARE_READ or FILE_SHARE_WRITE;
- end;
- hFile:=CreateFileA(pTransFileInfo^.clientFile,dwAccess,dwShare,nil,dwCreation,dwAtrr,0);
- if (hFile=INVALID_HANDLE_VALUE) then goto 1;
- fileSize:=GetFileSize(hFile,@fileSizeHigh);
- if (fileSize=$FFFFFFFF) and (GetLastError()<>NO_ERROR) then goto 1;
- if pTransFileInfo^.bUpLoad then
- begin
- if (fileSize=0) and (fileSizeHigh=0) then goto 1;
- end;//
- if not ConnectServer(hSocket,pTransFileInfo^.server) then goto 1;
- strcopy(RequestFileInfo.fileName,pTransFileInfo^.serverFile);
- RequestFileInfo.bUpLoad:=pTransFileInfo^.bUpLoad;
- //bTransType:=byte(RTransFile);
- //SendBuf(hSocket,@bTransType,sizeof(bTransType));
- formatOH(oh);oh.cmd:=CMD_FILE_TRANS;oh.len:=sizeof(RequestFileInfo);
- SendBuf(hSocket,@oh,sizeof(oh));
- SendBuf(hSocket,@RequestFileInfo,sizeof(RequestFileInfo));
- if pTransFileInfo^.bUpLoad then
- begin
- pTransFileInfo^.FileSize:=fileSize;//显示信息用;
- SendBuf(hSocket,@fileSize,sizeof(FileSize));
- SendBuf(hSocket,@fileSizeHigh,sizeof(fileSizeHigh));
- if not RecvBuf(hSocket,@srvFileSize,sizeof(srvFileSize)) then goto 1;
- if not RecvBuf(hSocket,@srvFileSizeHigh,sizeof(srvFileSizeHigh)) then goto 1;
- SetFilePointer(hFile,srvFileSize,@srvFileSizeHigh,FILE_BEGIN);
- pTransFileInfo^.transed:=srvFileSize;//显示信息用;
- while true do
- begin
- bRet:=ReadFile(hFile,buf,sizeof(buf),NumberOfRead,nil);
- if bRet=false then goto 1
- else if NumberOfRead=0 then begin result:=true;goto 1;end
- else begin
- if(not SendBuf(hSocket,@buf,NumberOfRead))then goto 1;
- pTransFileInfo^.aAPI:=FSend;//显示信息用;
- pTransFileInfo^.transed:=pTransFileInfo^.transed+NumberOfRead;//显示信息用;
- PostMessage(hform,wm_TransData,integer(FTransFile),integer(pTransFileInfo)); //显示信息用;
- end;//send(socket1,buf,NumberOfRead,0);
- end;//while
- end
- else begin
- err:=SetFilePointer(hFile,0,nil,FILE_END);
- if err=-1 then goto 1;
- SendBuf(hSocket,@fileSize,sizeof(fileSize));
- SendBuf(hSocket,@fileSizeHigh,sizeof(fileSizeHigh));
- pTransFileInfo^.transed:=fileSize;//显示信息用;
- while true do
- begin
- FillChar(buf,SizeOf(buf),0);
- recvLen:=RecvNon(hSocket,@buf,sizeof(buf));
- if recvLen=0 then result:=true;
- if (recvLen=-1) or (recvLen=0) then goto 1;
- //revs:=revs+revLen;
- if not WriteFile(hFile,Buf,recvLen,wLen,nil) then goto 1;
- pTransFileInfo^.aAPI:=FRecv;//显示信息用;
- pTransFileInfo^.transed:=pTransFileInfo^.transed+wLen;//显示信息用;
- PostMessage(hform,wm_TransData,integer(FTransFile),integer(pTransFileInfo)); //显示信息用
- end;//while
- end;//not if pTransFileInfo^.upLoad then
- 1:
- CloseHandle(hFile);
- FreeSocket(hSocket);
-
- end;
- function TransFilesClientThread(pTransFilesPara:pointer):BOOL;stdcall;
- var
- pTF:pTransFilesInfo;
- //err:integer;
- //bRet:bool;
- lpFindFileData: TWIN32FindDataA;
- hFind:Thandle;
- //severFile
- clientFile:array[0..MAX_PATH-1] of ansiChar;
- uniqueStr:array[0..64] of ansiChar;
- begin
- result:=false;
- pTF:=pTransFilesPara;
- pTF^.aAPI:=Fstart;
- PostMessage(hform,wm_TransData,integer(FTransFile),integer(pTF)); //显示信息用;
- if pTF^.bupLoad then
- begin
- hFind:=findfirstfileA(pTF^.clientFile,lpFindFileData);
- if hFind=INVALID_HANDLE_VALUE then exit;
- findclose(hFind);
- end;
- if pTF^.bFolder then
- begin
- if pTF^.bUpLoad then
- begin
- GettempPathA(MAXPATH,clientFile);
- StrFromTime(UniqueStr);
- strcat(clientFile,uniqueStr);
- strcat(clientFile,'.dir');
- //DirectoryCompression(pTF^.clientFile,clientFile);
- TZipFile.ZipDirectoryContents(clientFile,pTF^.clientFile);
- strcopy(pTF^.clientFile,clientFile);
- strcat(pTF^.serverFile,'.dir');
- end
- else begin
- strcopy(clientFile,pTF^.clientFile);
- strcat(pTF^.clientFile,'.dir');
- end;
- result:=TransFileClientThread(pTF);
- if pTF^.bUpLoad then //这儿可以删除上传后的目录
- DeleteFileA(pTF^.clientFile)
- else begin
- //DirectoryDecompression(clientFile,pTF^.clientFile);
- TZipFile.ExtractZipFile(pTF^.clientFile, clientFile);
- DeleteFileA(pTF^.clientFile);
- end;
- end
- else begin //是文件
- result:=TransFileClientThread(pTF);
- //如果是上传并且bCompleteDel=true ,删除原文件
- if (pTF^.bUpLoad and pTF^.bCompleteDel and result)=true then
- DeleteFileA(pTF^.clientFile);
- end;
- pTF^.aAPI:=Fend;
- SendMessage(hform,wm_TransData,integer(FTransFile),integer(pTF));
- dispose(pTF);
- end;
- procedure initAddr();
- begin
- DataSvrAddr.port:=uConfig.FTS_PORT;
- strcopy(DataSvrAddr.IP,pansiChar(uConfig.FTS_HOST));
-
- end;
- initialization
- initAddr();
-
- finalization
-
- end.
2、通讯单元
- unit uSocket;
-
- interface
- //************************windows定义**************************************
- const
- user32 = 'USER32.dll';
- //-------------------------------------------
- //数据传输协议包头:
- UID:integer=8888;//包头标识;
- VER:integer=1002;
- ENC:integer=7620;
-
- CMD_READY:integer=1001;
- type
- BOOL = LongBool;
- DWORD = LongWord;
-
- //************************socket 定义****************************
- type
- u_int = Integer;
- TSocket = u_int;
- u_short = Word;
- u_char = Char;
- u_long = Longint;
- const
- winsocket = 'WSock32.dll';
- SOCKET_ERROR = -1;
- INVALID_SOCKET = TSocket(NOT(0));
- WSADESCRIPTION_LEN = 256;
- WSASYS_STATUS_LEN = 128;
- AF_INET = 2;
- SOCK_STREAM = 1; { stream socket }
-
- SOL_SOCKET = $ffff; {options for socket level }
- SO_LINGER = $0080; { linger on close if data present }
- SO_SNDTIMEO = $1005; { send timeout }
- SO_RCVTIMEO = $1006; { receive timeout }
- WSAECONNRESET =10054;
- type
- SunB = packed record
- s_b1, s_b2, s_b3, s_b4: u_char;
- end;
- SunW = packed record
- s_w1, s_w2: u_short;
- end;
- PInAddr = ^TInAddr;
- in_addr = record
- case integer of
- 0: (S_un_b: SunB);
- 1: (S_un_w: SunW);
- 2: (S_addr: u_long);
- end;
- TInAddr = in_addr;
- PSockAddrIn = ^TSockAddrIn;
- sockaddr_in = record
- case Integer of
- 0: (sin_family: u_short;
- sin_port: u_short;
- sin_addr: TInAddr;
- sin_zero: array[0..7] of ansiChar);
- 1: (sa_family: u_short;
- sa_data: array[0..13] of ansiChar)
- end;
- TSockAddrIn = sockaddr_in;
- PSOCKADDR = ^TSockAddr;
- TSockAddr = sockaddr_in;
-
- PWSAData = ^TWSAData;
- WSAData = record // !!! also WSDATA
- wVersion: Word;
- wHighVersion: Word;
- szDescription: array[0..WSADESCRIPTION_LEN] of ansiChar;
- szSystemStatus: array[0..WSASYS_STATUS_LEN] of ansiChar;
- iMaxSockets: Word;
- iMaxUdpDg: Word;
- lpVendorInfo: PansiChar;
- end;
- TWSAData = WSAData;
- PHostEnt = ^THostEnt;
- {$EXTERNALSYM hostent}
- hostent = record
- h_name: PansiChar;
- h_aliases: ^PansiChar;
- h_addrtype: Smallint;
- h_length: Smallint;
- case Byte of
- 0: (h_addr_list: ^PansiChar);
- 1: (h_addr: ^PansiChar)
- end;
- THostEnt = hostent;
- //2006-04-25
- linger = record
- l_onoff: u_short;
- l_linger: u_short;
- end;
- timeval = record
- tv_sec: Longint;
- tv_usec: Longint;
- end;
- //************************我的 定义****************************
- type
- pSvrAddr=^stSvrAddr;
- stSvrAddr=packed record
- port:Word;
- case flg:byte of
- 0:(IP:array[0..15] of ansiChar);
- 1:(DN:array[0..30] of ansiChar);
- end;
- POrderHeader=^stOrderHeader;
- stOrderHeader=packed record
- uid:DWORD;
- Ver:DWORD;
- Enc:DWORD;
- id:DWORD;
- pid:DWORD;
- cmd:DWORD;
- len:DWORD;
- dat:pointer;
- end;
-
- //---------------------------------------------------------
- //***********************socket api***********************************
- function recv(s: TSocket; var Buf; len, flags: Integer): Integer; stdcall;
- function send(s: TSocket; var Buf; len, flags: Integer): Integer; stdcall;
- function connect(s: TSocket; var name: TSockAddr; namelen: Integer): Integer; stdcall;
- function closesocket(s: TSocket): Integer; stdcall;
- function WSACleanup: Integer; stdcall;
- function socket(af, Struct, protocol: Integer): TSocket; stdcall;
- function WSAStartup(wVersionRequired: word; var WSData: TWSAData): Integer; stdcall;
- function htons(hostshort: u_short): u_short; stdcall;
- function inet_addr(cp: PansiChar): u_long; stdcall; {PInAddr;} { TInAddr }
- function gethostbyname(name: PansiChar): PHostEnt; stdcall;
-
- function setsockopt(s: TSocket; level, optname: Integer; optval: PansiChar;
- optlen: Integer): Integer; stdcall;
- function WSAGetLastError: Integer; stdcall;
- //***********************windows api*************************************
- procedure ZeroMemory(Destination: Pointer; Length: DWORD);
- function wsprintf(Output: PansiChar; Format: PansiChar): Integer; stdcall;
-
-
- //***********************字符串函数*************************************
- function _wsprintf(lpOut: PansiChar; lpFmt: PansiChar; lpVars: Array of Const):Integer; assembler;
- //***********************我的函数*****************************************
- function InitAddr(sa:stSvrAddr;var addr:sockaddr_in):bool;stdcall;
- function HostToIP(hostName:pansiChar):in_addr;stdcall;
- function InitSocket(var hSocket:integer):bool;stdcall;
- procedure FreeSocket(var hSocket:integer);stdcall; //out
- function ConnectServer(var hSocket:integer;sa:stSvrAddr):bool;stdcall; //out
- function RecvBuf(hSocket:integer;p:pointer;len:DWORD):bool;stdcall;
- function SendBuf(socket:integer;p:pointer;size:DWORD):bool;stdcall;
- function GetLocalIP(IP:pansiChar):bool;stdcall;
- function RecvNon(hSocket:integer;p:pointer;len:integer):integer;stdcall;
- function VerifyOH(oh:stOrderHeader) :boolean;//校验包头;
- function formatOH(var oh:stOrderHeader) :stOrderHeader;//格式化包头;
- implementation
- //***********************windows api*************************************
- procedure ZeroMemory(Destination: Pointer; Length: DWORD);
- begin
- FillChar(Destination^, Length, 0);
- end;
- function wsprintf; external user32 name 'wsprintfA';
- //**********************socket api******************************************
- function recv; external winsocket name 'recv';
- function send; external winsocket name 'send';
- function connect; external winsocket name 'connect';
- function closesocket; external winsocket name 'closesocket';
- function WSACleanup; external winsocket name 'WSACleanup';
- function WSAStartup; external winsocket name 'WSAStartup';
- function socket; external winsocket name 'socket';
- function htons; external winsocket name 'htons';
- function inet_addr; external winsocket name 'inet_addr';
- function gethostbyname; external winsocket name 'gethostbyname';
-
- function setsockopt; external winsocket name 'setsockopt';
- function WSAGetLastError; external winsocket name 'WSAGetLastError';
- //***********************字符串函数*************************************
- function _wsprintf(lpOut:pansiChar;lpFmt:pansiChar;lpVars:array of const):integer;assembler;
- var
- count:integer;
- v1,v2:integer;
- asm
- mov v1,eax
- mov v2,edx
- mov eax,ecx
- mov ecx,[ebp+$08]
- inc ecx
- mov count,ecx
- dec ecx
- imul ecx,8
- add eax,ecx
- mov ecx,count
- @@1:
- mov edx,[eax]
- push edx
- sub eax,8
- loop @@1
-
- push v2
- push v1
-
- call wsprintf
-
- mov ecx,count
- imul ecx,4
- add ecx,8
- add esp,ecx
- end;
- //*********************我的函数****************************************
- function RecvNon(hSocket:integer;p:pointer;len:integer):integer;stdcall;
- begin
- result:=recv(hSocket,p^,len,0);
- end;
- function SendBuf(socket:integer;p:pointer;size:DWORD):bool;stdcall;
- var
- i,len:integer;
- pp:pointer;
- begin
- result:=false;
- len:=size;
- pp:=p;
- while len>0 do
- begin
- i:=send(socket,pp^,len,0);
- //if i=SOCKET_ERROR then exit; 2015-9-5
- if (i=SOCKET_ERROR) and (WSAGetLastError = WSAECONNRESET) then exit;
- len:=len-i;
- pp:=pointer(DWORD(pp)+DWORD(i));
- end;//while
- result:=true;
- end;
- function RecvBuf(hSocket:integer;p:pointer;len:DWORD):bool;stdcall;
- var
- err,k:integer;
- pp:pointer;
- begin
- result:=false;
- k:=len;
- pp:=p;
- while k>0 do
- begin
- err:=recv(hSocket,pp^,k,0);
- if (err=SOCKET_ERROR) or (err=0) then exit; //2015
- //if (err=SOCKET_ERROR) or (err=0) then exit;
- k:=k-err;
- pp:=pointer(dword(pp)+dword(err));
- end;
- result:=true;
- end;
- function ConnectServer(var hSocket:integer;sa:stSvrAddr):bool;stdcall;
- var
- err:integer;
- addr:sockaddr_in;
- begin
- result:=false;
- if not InitSocket(hSocket) then exit;
- InitAddr(sa,addr);
- err:=connect(hSocket,addr,sizeof(addr));//连接
- if err<>0 then FreeSocket(hSocket);
- result:=err=0;
- end;
- procedure FreeSocket(var hSocket:integer);stdcall;
- begin
- if hSocket<>0 then closesocket(hSocket);
- //WSACleanup();//终止WS2_32.DLL的使用
- hSocket:=0;
- end;
- {
- 功能描述:初始化Socket
- 入口参数:hSocket:Socket句柄
- 出口参数:返回值:成功创建返回True,否则返回False
- 创建日期:
- 修改记录:增加超时时间6分钟
- 2006-04-25
- Author:byc
- }
- function InitSocket(var hSocket:integer):bool;stdcall;
- var
- wsadata: TWSAData;
- err:integer;
- //t:linger;
- //timeout: timeval;
- tv:longint;
- begin
- result:=false;
- err:=WSAStartup($0202,wsadata);
- if err<>0 then
- begin //初始化WS2_32.DLL
- //showmessage('初始化ws_32.dll失败!');
- WSACleanup();//终止WS2_32.DLL的使用
- exit;
- end;//if
- hSocket:=socket(AF_INET, SOCK_STREAM, 0);
- //创建socket
- if hSocket=INVALID_SOCKET then
- begin
- //ShowMessage('创建SOCKET失败!');
- hSocket:=0;
- WSACleanup();
- exit;
- end;//if socket1=SOCKET_ERROR then
- {
- t.l_onoff:=1;
- t.l_linger:=0;
- //关闭socket后立刻释放资源
- err:=setsockopt(hSocket,SOL_SOCKET,SO_LINGER,@t,sizeof(t));
- if err=SOCKET_ERROR then
- begin
- FreeSocket(hSocket);
- exit;
- end;
- }
- //set recv and send timeout
- tv:=6*60*1000;
- //tv:=60000;//测试
- err:=setsockopt(hSocket,SOL_SOCKET,SO_SNDTIMEO,@tv,sizeof(timeval));
- if err=SOCKET_ERROR then
- begin
- FreeSocket(hSocket);
- exit;
- end;
- err:=setsockopt(hSocket,SOL_SOCKET,SO_RCVTIMEO,@tv,sizeof(timeval));
- if err=SOCKET_ERROR then
- begin
- FreeSocket(hSocket);
- exit;
- end;
- result:=true;
- end;
- function InitAddr(sa:stSvrAddr;var addr:sockaddr_in):bool;stdcall;
- begin
- result:=false;
- zeromemory(@addr,sizeof(addr));
- addr.sin_family:=AF_INET;
- addr.sin_port:=htons(sa.port);
- case sa.flg of
- 0:begin
- addr.sin_addr.S_addr:=inet_addr(sa.IP);
- end;//0
- 1:begin
- addr.sin_addr:=HostToIP(sa.DN);
- end;//1
- end;//case
- if addr.sin_addr.S_addr>0 then
- result:=true;
- end;
- function HostToIP(hostName:pansiChar):in_addr;stdcall;
- var
- hostEnt : PHostEnt;
- addr:pansiChar;
- err:integer;
- wd:wsadata;
- begin
- err:=WSAStartup($0202,WD);
- if err<>0 then exit;
- ZeroMemory(@result,sizeof(in_addr));
- hostEnt:=gethostbyname (hostName);
- if Assigned (hostEnt) then
- if Assigned (hostEnt^.h_addr_list) then
- begin
- addr := hostEnt^.h_addr_list^;
- if Assigned (addr) then
- begin
- result:=PInAddr(addr)^;
- end;// if Assigned (addr) then
- end;//if Assigned (hostEnt) then
- wsacleanup();
- end;
- function GetLocalIP(IP:pansiChar):bool;stdcall;
- var
- wd:WSAdata;
- err:integer;
- phe:PhostEnt;
- addr:pansiChar;
- b0,b1,b2,b3:byte;
- begin
- result:=false;
- err:=WSAStartup($101,wd);
- if err<>0 then begin wsaCleanup;exit;end;
- phe:=GetHostByName(nil);
- if phe=nil then begin wsaCleanup;exit;end;
- addr:=(phe^.h_addr)^;
- if addr=nil then begin wsaCleanup;exit;end;
- b0:=byte((addr+0)^);b1:=byte((addr+1)^);
- b2:=byte((addr+2)^);b3:=byte((addr+3)^);
- _wsprintf(IP,'%d.%d.%d.%d',[b0,b1,b2,b3]);
- wsaCleanup;
- result:=true;
- end;
- //-------------------------------------------------------------------------
- function VerifyOH(oh:stOrderHeader) :boolean;//校验包头;
- begin
- result:=true;
- if(oh.uid<>UID)then result:=false;
- if(oh.Ver<>VER)then result:=false;
- if(oh.ENC<>ENC)then result:=false;
- end;
- function formatOH(var oh:stOrderHeader) :stOrderHeader;//格式化包头;
- begin
- oh.uid:=UID;
- oh.Ver:=VER;
- oh.Enc:=ENC;
- oh.id:=0;
- oh.pid:=0;
- oh.cmd:=CMD_READY;
- oh.len:=0;
- oh.dat:=nil;
- result:=oh;
- end;
- //------------------------------------------------------------------
- end.
3、客户端主线程
- unit uMain;
-
- interface
-
- uses
- Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
- Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ComCtrls,
- Vcl.FileCtrl, Vcl.ExtCtrls,strutils,system.zip,IdGlobalProtocols,
- uConfig,uLog,uTransFileClient,uDes2010,uFuncs, Vcl.Menus,shellapi;
-
- type
- TfMain = class(TForm)
- Panel4: TPanel;
- Label2: TLabel;
- Label1: TLabel;
- edtAddr: TEdit;
- edtPort: TEdit;
- btnUpload: TButton;
- btnDownload: TButton;
- btnClose: TButton;
- Bar1: TStatusBar;
- Panel2: TPanel;
- Drive1: TDriveComboBox;
- Dir1: TDirectoryListBox;
- Splitter1: TSplitter;
- Panel3: TPanel;
- File1: TFileListBox;
- edtFile: TEdit;
- Splitter2: TSplitter;
- Panel1: TPanel;
- Splitter3: TSplitter;
- ListFileInfo: TListView;
- memoInfo: TMemo;
- btnList: TButton;
- btnSelAll: TButton;
- btnDecryptFile: TButton;
- lbDir: TLabel;
- popDir: TPopupMenu;
- N1: TMenuItem;
- N2: TMenuItem;
- popFile: TPopupMenu;
- MenuItem1: TMenuItem;
- MenuItem2: TMenuItem;
- N3: TMenuItem;
- N4: TMenuItem;
- procedure btnUploadClick(Sender: TObject);
- procedure FormShow(Sender: TObject);
- procedure btnCloseClick(Sender: TObject);
- procedure btnDownloadClick(Sender: TObject);
- procedure btnListClick(Sender: TObject);
- procedure FormCreate(Sender: TObject);
- procedure btnSelAllClick(Sender: TObject);
- procedure ListFileInfoColumnClick(Sender: TObject; Column: TListColumn);
- procedure btnDecryptFileClick(Sender: TObject);
- procedure N1Click(Sender: TObject);
- procedure MenuItem1Click(Sender: TObject);
- procedure MenuItem2Click(Sender: TObject);
- procedure N3Click(Sender: TObject);
- procedure N4Click(Sender: TObject);
- procedure N2Click(Sender: TObject);
-
- private
- { Private declarations }
- procedure TransDataMsg(var msg:TMessage);message wm_TransData;
- procedure TryExcepts(Sender: TObject; E: Exception);
- procedure parseFileList();
- procedure AddList(filesign,filesize:string);
- function decryptFilename(filename:string):string;
- procedure decryptfile(ss:tstrings);
- public
- { Public declarations }
- end;
-
- var
- fMain: TfMain;
- function CustomSortProc(Item1, Item2: TListItem; ColumnIndex: integer): integer; stdcall;
- function cryptfile(filedir:string):ansiString;
- //联系QQ:39848872微信:byc6352
- implementation
-
- {$R *.dfm}
- procedure TfMain.decryptfile(ss:tstrings);
- const
- FILE_NAME_ID='x';
- var
- i:integer;
- filename,newfilename,newdir:string;
- begin
- for I := 0 to ss.Count-1 do
- begin
- filename:=ss[i];
- if(filename[length(filename)]<>FILE_NAME_ID)then continue;
- if(FileSizeByName(filename)=0)then
- begin
- deletefile(filename);
- continue;
- end;
- uFuncs.cryptfile(filename);
- newfilename:=leftstr(filename,length(filename)-1);
- newfilename:=extractfilepath(newfilename)+uDes2010.DecryStrHex(extractfilename(newfilename),uConfig.key);
- movefile(pchar(filename),pchar(newfilename));
- newdir:=leftstr(newfilename,length(newfilename)-4);
- if(TZipFile.IsValid(newfilename))then
- begin
- TZipFile.ExtractZipFile(newfilename, newdir);
- deletefile(newfilename);
- end else begin
- memoInfo.Lines.Add('解压失败:'+newfilename);
- //showmessage('解压失败:'+newfilename);
- end;
- //uzip.DirectoryDecompression(newdir,newfilename);
- end;
- end;
- //'c:\temp\0310\2'
- function cryptfile(filedir:string):ansiString;
- var
- filename:array[0..MAX_PATH-1] of ansiChar;
- filesize:array[0..31] of ansiChar;
- wfd:WIN32_FIND_DATAA;
- hFindFile:THANDLE;
- newfilename,newdir:ansistring;
- begin
- result:='';
- strcopy(filename,pansichar(ansiString(filedir)));
- strcat(filename,pansichar('\*'));
- hFindFile:=FindFirstFileA(filename,wfd);
- if hFindFile=INVALID_HANDLE_VALUE then exit;
- while(FindNextFileA(hFindFile,wfd))do
- begin
- if(wfd.cFileName[0]='.')then continue;
- if(wfd.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY)<>0 then continue;
- //uFuncs.cryptfile(filedir+'\'+wfd.cFileName);
- newfilename:=filedir+'\'+wfd.cFileName;
- newdir:=leftstr(newfilename,length(newfilename)-4);
- if(TZipFile.IsValid(newfilename))then
- begin
- try
- TZipFile.ExtractZipFile(newfilename, newdir);
- except
- fmain.memoInfo.Lines.Add('解压失败1:'+newfilename);
- end;
- deletefile(newfilename);
- end else begin
- fmain.memoInfo.Lines.Add('解压失败:'+newfilename);
- //showmessage('解压失败:'+newfilename);
- end;
- end;
- Winapi.Windows.FindClose(hFindFile);
- end;
- function TfMain.decryptFilename(filename:string):string;
- const
- FILE_NAME_ID='x';
- var
- i:integer;
- newfilename,newdir:string;
- begin
- result:=filename;
- try
- if(filename[length(filename)]<>FILE_NAME_ID)then exit;
- newfilename:=leftstr(filename,length(filename)-1);
- newfilename:=uDes2010.DecryStrHex(newfilename,uConfig.key);
- result:=newfilename;
- finally
-
- end;
- end;
- procedure TfMain.AddList(filesign,filesize:string);
- var
- item:tListitem;
- begin
- item:=ListFileInfo.Items.Add;
- item.Caption:=filesign;
- item.SubItems.Add(decryptFilename(filesign));
- item.SubItems.Add(filesize);
- item.SubItems.Add('');
- item.ImageIndex:=8;
- end;
- procedure TfMain.parseFileList();
- var
- filelist,fileinfo:tstrings;
- i:integer;
- filename,info:string;
- begin
- if gFileList='' then exit;
- ListFileInfo.Clear;
- try
- filelist:=tstringlist.Create;
- fileinfo:=tstringlist.Create;
- if gFileList[length(gFileList)]=';' then delete(gFileList,length(gFileList),1);
- if(rightstr(gFileList,2)=#13#10) then leftstr(gFileList,length(gFileList)-2);
- fileList.Text:=gFileList;
- if(fileList.Count=0)then exit;
- for I := 0 to fileList.Count-1 do
- begin
- info:=fileList[i];
- fileinfo.Delimiter:=';';
- fileinfo.DelimitedText:=info;
- AddList(fileinfo[0],fileinfo[1]);
- end;
- bar1.Panels[0].Text:='共有文件:'+inttostr(filelist.Count);
- finally
- filelist.Free;
- fileinfo.Free;
-
- end;
- end;
- procedure tFMain.TransDataMsg(var msg:TMessage);
- var
- threadType:TThreadType;
- pTF:pTransFilesInfo;
- localfilename,newfilename,localpath:ansiString;
- i:integer;
- begin
- threadType:=TThreadType(msg.WParam);
- case threadType of
- FListFile:
- begin
- //memoSms.Lines.Add(gFileList);
- parseFileList();
- ListFileInfo.CustomSort(@CustomSortProc,0);
- end;
- FTransFile:
- begin
- pTF:=pTransFilesInfo(msg.LParam);
- if(pTF<>nil)then
- begin
- localfilename:=pTF^.clientFile;
- //memoInfo.lines.add(localfilename);
- if(pTF^.aAPI=Fstart)then
- begin
- memoInfo.lines.add('开始传输:'+localfilename);
- bar1.Panels[0].Text:='开始传输:'+localfilename;
- end;
- if(pTF^.bUpLoad)then
- begin
- if pTF^.aAPI=Fsend then
- bar1.Panels[0].Text:='正在上传:'+inttostr(pTF^.transed)+'/'+inttostr(pTF^.FileSize);
- if pTF^.aAPI=Fend then
- begin
- btnList.Click();
- memoInfo.lines.add('上传完成:'+localfilename);
- bar1.Panels[0].Text:='上传完成:'+inttostr(pTF^.transed)+'/'+inttostr(pTF^.FileSize);
- end;
- end else begin
- i:=ptF^.threadId;
- if pTF^.aAPI=FRecv then
- begin
- listFileInfo.Items[i].SubItems.Strings[2]:=inttostr(pTF^.transed);
- bar1.Panels[0].Text:='正在下载:'+inttostr(pTF^.transed);
- end;
- if pTF^.aAPI=Fend then
- begin
- localpath:=extractfilepath(localfilename);
- {
- newfilename:=localpath+decryptFilename(extractfilename(localfilename));
- if(newfilename<>localfilename)then
- begin
- renamefile(localfilename,newfilename);
- uFuncs.cryptfile(newfilename);
- end;
- }
- memoInfo.lines.add('下载完成:'+localfilename);
- bar1.Panels[0].Text:='下载完成:'+inttostr(pTF^.transed);
- listFileInfo.Items[i].SubItems.Strings[2]:='下载完成'+inttostr(pTF^.transed);
- file1.Update;
- end;
- end;
- //loadfile(localfilename);
- end;
- end;
- end;
- end;
- procedure TfMain.TryExcepts(Sender: TObject; E: Exception);
- begin
- Log(E.Message);
- //memoINfo.Lines.Add(Log(E.Message));
- //Log(
- end;
- procedure TfMain.btnCloseClick(Sender: TObject);
- begin
- close;
- end;
-
- procedure TfMain.btnDownloadClick(Sender: TObject);
- var
- localFilename,remoteFilename:string;
- i:integer;
- begin
- if(ListFileInfo.SelCount=0)then
- begin
- showmessage('请选择要下载的文件!');
- exit;
- end;
- for I := 0 to ListFileInfo.Items.Count-1 do
- begin
- if(ListFileInfo.Items[i].Selected)then
- begin
- remoteFilename:=ListFileInfo.Items[i].Caption;
- localFilename:=file1.Directory+'\'+remoteFilename;
- uTransFileClient.downloadFile(localFilename,remoteFilename,i);
- end;
- end;
-
-
-
-
-
- end;
-
- procedure TfMain.btnListClick(Sender: TObject);
- begin
- uTransFileClient.ProcessListFile();
- end;
-
- procedure TfMain.btnSelAllClick(Sender: TObject);
- begin
- ListFileInfo.SelectAll;
- end;
-
- procedure TfMain.btnDecryptFileClick(Sender: TObject);
- begin
- //cryptfile('c:\temp\0310\2');
- decryptfile(file1.Items);
- dir1.Update;
- file1.Update;
-
- bar1.Panels[1].Text:=''+inttostr(file1.Items.Count)+'个文件';
- end;
-
- procedure TfMain.btnUploadClick(Sender: TObject);
- var
- localFilename,remoteFilename:string;
- i:integer;
- begin
- if(file1.SelCount=0)then
- begin
- showmessage('请选择要上传的文件!');
- exit;
- end;
- for i := 0 to file1.Count-1 do
- begin
- if(file1.Selected[i])then
- begin
- localFilename:=file1.Items[i];
- remoteFilename:=extractfilename(localFilename);
- uTransFileClient.uploadFile(localFilename,remoteFilename);
- end;
- end;
-
- //localFilename:=file1.FileName;
- //remoteFilename:=extractfilename(localFilename);
- //uTransFileClient.uploadFile(localFilename,remoteFilename);
- end;
-
- procedure TfMain.FormCreate(Sender: TObject);
- begin
- application.OnException:=TryExcepts;
- end;
-
- procedure TfMain.FormShow(Sender: TObject);
- begin
- //fmain.Caption:=uConfig.APP_NAME+uConfig.APP_VERSION+uConfig.APP_CONTACT;
- fmain.Caption:=uConfig.APP_NAME+uConfig.APP_VERSION;
- edtAddr.Text:=uConfig.FTS_HOST_FORGED;
- edtPort.Text:=inttostr(uConfig.FTS_PORT);
- uTransFileClient.hForm:=fmain.Handle;
- btnList.Click();
- dir1.Drive:='c';
- dir1.Directory:='c:\temp';
- end;
-
-
-
- procedure TfMain.ListFileInfoColumnClick(Sender: TObject; Column: TListColumn);
- begin
- ListFileInfo.CustomSort(@CustomSortProc,Column.Index);
- end;
-
- procedure TfMain.MenuItem1Click(Sender: TObject);
- var
- filename:string;
- begin
- if File1.Count=0 then exit;
- if File1.ItemIndex=-1 then exit;
- filename:=File1.Items[File1.ItemIndex];
- ShellExecute(Handle,pchar('open'), pchar('explorer.exe'), pchar('/select,'+filename), nil, SW_SHOW);
-
- end;
-
- procedure TfMain.MenuItem2Click(Sender: TObject);
- var
- filename:string;
- begin
- if File1.Count=0 then exit;
- if File1.ItemIndex=-1 then exit;
- filename:=File1.Items[File1.ItemIndex];
- ShellExecute(Handle,pchar('open'), pchar('explorer.exe'), pchar(filename), nil, SW_SHOW);
-
- end;
-
- procedure TfMain.N1Click(Sender: TObject);
- var
- dir,dirname:string;
- begin
- dir:=dir1.Directory;
- dirname:= InputBox('请输入目录名:','目录名:','');//参数分别为标题,提示,默认值
- if dirname<>'' then
- begin
- ForceDirectories(dir+'\'+dirname);
- dir1.Update;
- end;
- end;
-
- procedure TfMain.N2Click(Sender: TObject);
- var
- dir:string;
- begin
- if dir1.Count=0 then exit;
- if dir1.ItemIndex=-1 then exit;
- dir:=dir1.Items[File1.ItemIndex];
- uFuncs.deldir(dir) ;
- dir1.Update;
- end;
-
- procedure TfMain.N3Click(Sender: TObject);
- var
- filename,newfilename:string;
- begin
- if File1.Count=0 then exit;
- if File1.ItemIndex=-1 then exit;
- filename:=File1.Items[File1.ItemIndex];
- newfilename:= InputBox('请输入文件名:','文件名:','');//参数分别为标题,提示,默认值
- if newfilename<>'' then
- begin
- movefile(pchar(filename),pchar(newfilename));
- File1.Update;
- end;
-
- end;
-
- procedure TfMain.N4Click(Sender: TObject);
- var
- filename:string;
- begin
- if File1.Count=0 then exit;
- if File1.ItemIndex=-1 then exit;
- filename:=File1.Items[File1.ItemIndex];
- deletefile(filename);
- file1.Update;
- end;
-
- function CustomSortProc(Item1, Item2: TListItem; ColumnIndex: integer): integer; stdcall;
- begin
- if ColumnIndex = 0 then
- Result := CompareText(Item1.Caption,Item2.Caption)
- else
- Result := CompareText(Item1.SubItems[ColumnIndex-1],Item2.SubItems[ColumnIndex-1])
- end;
- end.
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。