当前位置:   article > 正文

二、delphi 开发的基于win socket文件传输系统(支持超4G文件,断点续传,多线程同时能传输100个文件以上,支持文件夹压缩传输)客户端_delphi 开发的基于win socket文件传输系统(支持超4g文... -

delphi 开发的基于win socket文件传输系统(支持超4g文... -

delphi 自带的TIdFtpServer和TIdFtpClient组件,在实际应用中发现,只能单线程传输较小的文件。有很大局限性。决定自己写一个文件传输系统。该传输系统经测试,可以同时传输100个文件以上,超过4G大小的文件,支持断点续传。同时支持对文件夹的压缩传输。基本满足业务的要求。现在把服务器端和客户端代码粘贴如下:

一、客户端

1、传输单元

 

 

  1. unit uTransFileClient;
  2. interface
  3. uses windows,graphics,classes,zip,uSocket,uStr,uConfig;
  4. const
  5. MAXPATH=260;
  6. MAXBUF=8192;
  7. CMD_FILE_LIST=4001;//列举目录;传递绝对路径;
  8. CMD_FILE_TRANS=4002;//文件传输
  9. CMD_FILE_DEL=4003;//删除文件
  10. wm_user=$0400;
  11. wm_TransData=wm_user+100+1;
  12. type
  13. TAPIFlag=(Fstart,Frecv,Fsend,Fend);
  14. TThreadType=(FListFile,FTransFile);
  15. pTransFilesInfo=^stTransFilesInfo;
  16. stTransFilesInfo=packed record
  17. server:stSvrAddr;
  18. clientFile:array[0..MAX_PATH-1] of ansiChar;
  19. serverFile:array[0..MAX_PATH-1] of ansiChar;
  20. bUpLoad:bool;
  21. bFolder:bool;
  22. bCompleteDel:bool;
  23. aAPI:TAPIFlag;
  24. transed:cardinal;
  25. FileSize:cardinal;
  26. threadId:integer;
  27. end;
  28. pRequestFileInfo=^stRequestFileInfo;
  29. stRequestFileInfo=packed record
  30. fileName:array[0..MAX_PATH-1] of ansiChar;
  31. bUpLoad:bool;
  32. end;//
  33. pRecvData=^stRecvData;
  34. stRecvData=packed record
  35. server:stSvrAddr;
  36. data:pointer;
  37. dataSize:integer;
  38. end;
  39. pListFile=^stListFile;
  40. stListFile=packed record
  41. server:stSvrAddr;
  42. filename:array[0..MAX_PATH-1] of ansiChar;
  43. data:pointer;
  44. dataSize:integer;
  45. end;
  46. function TransFilesClientThread(pTransFilesPara:pointer):BOOL;stdcall;
  47. function TransFileClientThread(pTransFilePara:pointer):bool;stdcall;
  48. procedure ProcessTransFile(const LocalFilename,RemoteFilename:ansiString;bUpload:boolean);overload;
  49. procedure ProcessTransFile(const LocalFilename,RemoteFilename:ansiString;bUpload:boolean;threadId:integer);overload;
  50. procedure initAddr();
  51. procedure uploadFile(const LocalFilename,RemoteFilename:ansiString);
  52. procedure downloadFile(const LocalFilename,RemoteFilename:ansiString);overload;
  53. procedure downloadFile(const LocalFilename,RemoteFilename:ansiString;threadId:integer);overload;
  54. function ListFileThread():bool;stdcall;
  55. procedure ProcessListFile();
  56. var
  57. DataSvrAddr:stSvrAddr;
  58. gFileList:ansiString;
  59. hForm:THANDLE;
  60. implementation
  61. procedure ProcessListFile();
  62. var
  63. hd,id:cardinal;
  64. begin
  65. gFileList:='';
  66. hd:=createthread(nil,0,@ListFileThread,nil,0,id);
  67. closehandle(hd);
  68. end;
  69. function ListFileThread():bool;stdcall;
  70. var
  71. hSocket:integer;
  72. oh:stOrderHeader;
  73. begin
  74. result:=false;
  75. try
  76. if not ConnectServer(hSocket,DataSvrAddr) then exit;
  77. formatOH(oh);oh.cmd:=CMD_FILE_LIST;
  78. SendBuf(hSocket,@oh,sizeof(oh));
  79. //SendBuf(hSocket,@pList^.filename[0],MAX_PATH);
  80. if not RecvBuf(hSocket,@oh,sizeof(oh)) then exit;
  81. if(oh.len<=0)then exit;
  82. setlength(gFileList,oh.len);
  83. if not RecvBuf(hSocket,@gFileList[1],oh.len) then exit;
  84. finally
  85. SendMessage(hform,wm_TransData,integer(FListFile),0);
  86. FreeSocket(hSocket);
  87. end;
  88. end;
  89. procedure uploadFile(const LocalFilename,RemoteFilename:ansiString);
  90. begin
  91. ProcessTransFile(LocalFilename,RemoteFilename,true);
  92. end;
  93. procedure downloadFile(const LocalFilename,RemoteFilename:ansiString);
  94. var
  95. uploadfile:string;
  96. begin
  97. uploadfile:='\upload\'+RemoteFilename;
  98. ProcessTransFile(LocalFilename,uploadfile,false);
  99. end;
  100. procedure downloadFile(const LocalFilename,RemoteFilename:ansiString;threadId:integer);
  101. var
  102. uploadfile:string;
  103. begin
  104. uploadfile:='\upload\'+RemoteFilename;
  105. ProcessTransFile(LocalFilename,uploadfile,false,threadId);
  106. end;
  107. procedure ProcessTransFile(const LocalFilename,RemoteFilename:ansiString;bUpload:boolean;threadId:integer);
  108. var
  109. pTF:pTransFilesInfo;
  110. hd,id:cardinal;
  111. begin
  112. new(pTF);
  113. zeromemory(pTF,sizeof(stTransFilesInfo));
  114. strcopy(pTF^.clientFile,pansichar(LocalFilename));
  115. strcopy(pTF^.serverFile,pansichar(RemoteFilename));
  116. pTF^.bUpLoad:=bUpload;
  117. pTF^.bFolder:=false;
  118. pTF^.bCompleteDel:=false;
  119. pTF^.server:=DataSvrAddr;
  120. pTF^.threadId:=threadId;
  121. hd:=createthread(nil,0,@TransFilesClientThread,pTF,0,id);
  122. closehandle(hd);
  123. end;
  124. procedure ProcessTransFile(const LocalFilename,RemoteFilename:ansiString;bUpload:boolean);
  125. var
  126. pTF:pTransFilesInfo;
  127. hd,id:cardinal;
  128. begin
  129. new(pTF);
  130. zeromemory(pTF,sizeof(stTransFilesInfo));
  131. strcopy(pTF^.clientFile,pansichar(LocalFilename));
  132. strcopy(pTF^.serverFile,pansichar(RemoteFilename));
  133. pTF^.bUpLoad:=bUpload;
  134. pTF^.bFolder:=false;
  135. pTF^.bCompleteDel:=false;
  136. pTF^.server:=DataSvrAddr;
  137. hd:=createthread(nil,0,@TransFilesClientThread,pTF,0,id);
  138. closehandle(hd);
  139. end;
  140. function TransFileClientThread(pTransFilePara:pointer):bool;stdcall;
  141. label 1;
  142. var
  143. pTransFileInfo:pTransFilesInfo;
  144. hSocket:integer;
  145. hFile,FileSize,NumberOfRead,srvFileSize,wLen,fileSizeHigh,srvFileSizeHigh:cardinal;
  146. err,recvLen:integer;
  147. buf:array[0..MAXBUF-1] of ansiChar;
  148. RequestFileInfo:stRequestFileInfo;
  149. bRet:LongBool;
  150. bTransType:byte;
  151. dwAccess,dwCreation,dwAtrr,dwShare:DWORD;
  152. oh:stOrderHeader;
  153. begin
  154. result:=false;
  155. pTransFileInfo:=pTransFilePara;
  156. if pTransFileInfo^.bUpLoad then
  157. begin
  158. dwAccess:=GENERIC_READ;
  159. dwCreation:=OPEN_EXISTING;
  160. dwAtrr:=FILE_ATTRIBUTE_NORMAL;
  161. dwShare:=FILE_SHARE_READ;
  162. end
  163. else begin
  164. dwAccess:=GENERIC_READ or GENERIC_WRITE;
  165. dwCreation:=OPEN_ALWAYS;
  166. dwAtrr:=FILE_ATTRIBUTE_NORMAL or FILE_ATTRIBUTE_ARCHIVE;
  167. dwShare:=FILE_SHARE_DELETE or FILE_SHARE_READ or FILE_SHARE_WRITE;
  168. end;
  169. hFile:=CreateFileA(pTransFileInfo^.clientFile,dwAccess,dwShare,nil,dwCreation,dwAtrr,0);
  170. if (hFile=INVALID_HANDLE_VALUE) then goto 1;
  171. fileSize:=GetFileSize(hFile,@fileSizeHigh);
  172. if (fileSize=$FFFFFFFF) and (GetLastError()<>NO_ERROR) then goto 1;
  173. if pTransFileInfo^.bUpLoad then
  174. begin
  175. if (fileSize=0) and (fileSizeHigh=0) then goto 1;
  176. end;//
  177. if not ConnectServer(hSocket,pTransFileInfo^.server) then goto 1;
  178. strcopy(RequestFileInfo.fileName,pTransFileInfo^.serverFile);
  179. RequestFileInfo.bUpLoad:=pTransFileInfo^.bUpLoad;
  180. //bTransType:=byte(RTransFile);
  181. //SendBuf(hSocket,@bTransType,sizeof(bTransType));
  182. formatOH(oh);oh.cmd:=CMD_FILE_TRANS;oh.len:=sizeof(RequestFileInfo);
  183. SendBuf(hSocket,@oh,sizeof(oh));
  184. SendBuf(hSocket,@RequestFileInfo,sizeof(RequestFileInfo));
  185. if pTransFileInfo^.bUpLoad then
  186. begin
  187. pTransFileInfo^.FileSize:=fileSize;//显示信息用;
  188. SendBuf(hSocket,@fileSize,sizeof(FileSize));
  189. SendBuf(hSocket,@fileSizeHigh,sizeof(fileSizeHigh));
  190. if not RecvBuf(hSocket,@srvFileSize,sizeof(srvFileSize)) then goto 1;
  191. if not RecvBuf(hSocket,@srvFileSizeHigh,sizeof(srvFileSizeHigh)) then goto 1;
  192. SetFilePointer(hFile,srvFileSize,@srvFileSizeHigh,FILE_BEGIN);
  193. pTransFileInfo^.transed:=srvFileSize;//显示信息用;
  194. while true do
  195. begin
  196. bRet:=ReadFile(hFile,buf,sizeof(buf),NumberOfRead,nil);
  197. if bRet=false then goto 1
  198. else if NumberOfRead=0 then begin result:=true;goto 1;end
  199. else begin
  200. if(not SendBuf(hSocket,@buf,NumberOfRead))then goto 1;
  201. pTransFileInfo^.aAPI:=FSend;//显示信息用;
  202. pTransFileInfo^.transed:=pTransFileInfo^.transed+NumberOfRead;//显示信息用;
  203. PostMessage(hform,wm_TransData,integer(FTransFile),integer(pTransFileInfo)); //显示信息用;
  204. end;//send(socket1,buf,NumberOfRead,0);
  205. end;//while
  206. end
  207. else begin
  208. err:=SetFilePointer(hFile,0,nil,FILE_END);
  209. if err=-1 then goto 1;
  210. SendBuf(hSocket,@fileSize,sizeof(fileSize));
  211. SendBuf(hSocket,@fileSizeHigh,sizeof(fileSizeHigh));
  212. pTransFileInfo^.transed:=fileSize;//显示信息用;
  213. while true do
  214. begin
  215. FillChar(buf,SizeOf(buf),0);
  216. recvLen:=RecvNon(hSocket,@buf,sizeof(buf));
  217. if recvLen=0 then result:=true;
  218. if (recvLen=-1) or (recvLen=0) then goto 1;
  219. //revs:=revs+revLen;
  220. if not WriteFile(hFile,Buf,recvLen,wLen,nil) then goto 1;
  221. pTransFileInfo^.aAPI:=FRecv;//显示信息用;
  222. pTransFileInfo^.transed:=pTransFileInfo^.transed+wLen;//显示信息用;
  223. PostMessage(hform,wm_TransData,integer(FTransFile),integer(pTransFileInfo)); //显示信息用
  224. end;//while
  225. end;//not if pTransFileInfo^.upLoad then
  226. 1:
  227. CloseHandle(hFile);
  228. FreeSocket(hSocket);
  229. end;
  230. function TransFilesClientThread(pTransFilesPara:pointer):BOOL;stdcall;
  231. var
  232. pTF:pTransFilesInfo;
  233. //err:integer;
  234. //bRet:bool;
  235. lpFindFileData: TWIN32FindDataA;
  236. hFind:Thandle;
  237. //severFile
  238. clientFile:array[0..MAX_PATH-1] of ansiChar;
  239. uniqueStr:array[0..64] of ansiChar;
  240. begin
  241. result:=false;
  242. pTF:=pTransFilesPara;
  243. pTF^.aAPI:=Fstart;
  244. PostMessage(hform,wm_TransData,integer(FTransFile),integer(pTF)); //显示信息用;
  245. if pTF^.bupLoad then
  246. begin
  247. hFind:=findfirstfileA(pTF^.clientFile,lpFindFileData);
  248. if hFind=INVALID_HANDLE_VALUE then exit;
  249. findclose(hFind);
  250. end;
  251. if pTF^.bFolder then
  252. begin
  253. if pTF^.bUpLoad then
  254. begin
  255. GettempPathA(MAXPATH,clientFile);
  256. StrFromTime(UniqueStr);
  257. strcat(clientFile,uniqueStr);
  258. strcat(clientFile,'.dir');
  259. //DirectoryCompression(pTF^.clientFile,clientFile);
  260. TZipFile.ZipDirectoryContents(clientFile,pTF^.clientFile);
  261. strcopy(pTF^.clientFile,clientFile);
  262. strcat(pTF^.serverFile,'.dir');
  263. end
  264. else begin
  265. strcopy(clientFile,pTF^.clientFile);
  266. strcat(pTF^.clientFile,'.dir');
  267. end;
  268. result:=TransFileClientThread(pTF);
  269. if pTF^.bUpLoad then //这儿可以删除上传后的目录
  270. DeleteFileA(pTF^.clientFile)
  271. else begin
  272. //DirectoryDecompression(clientFile,pTF^.clientFile);
  273. TZipFile.ExtractZipFile(pTF^.clientFile, clientFile);
  274. DeleteFileA(pTF^.clientFile);
  275. end;
  276. end
  277. else begin //是文件
  278. result:=TransFileClientThread(pTF);
  279. //如果是上传并且bCompleteDel=true ,删除原文件
  280. if (pTF^.bUpLoad and pTF^.bCompleteDel and result)=true then
  281. DeleteFileA(pTF^.clientFile);
  282. end;
  283. pTF^.aAPI:=Fend;
  284. SendMessage(hform,wm_TransData,integer(FTransFile),integer(pTF));
  285. dispose(pTF);
  286. end;
  287. procedure initAddr();
  288. begin
  289. DataSvrAddr.port:=uConfig.FTS_PORT;
  290. strcopy(DataSvrAddr.IP,pansiChar(uConfig.FTS_HOST));
  291. end;
  292. initialization
  293. initAddr();
  294. finalization
  295. end.

 

 

2、通讯单元

  1. unit uSocket;
  2. interface
  3. //************************windows定义**************************************
  4. const
  5. user32 = 'USER32.dll';
  6. //-------------------------------------------
  7. //数据传输协议包头:
  8. UID:integer=8888;//包头标识;
  9. VER:integer=1002;
  10. ENC:integer=7620;
  11. CMD_READY:integer=1001;
  12. type
  13. BOOL = LongBool;
  14. DWORD = LongWord;
  15. //************************socket 定义****************************
  16. type
  17. u_int = Integer;
  18. TSocket = u_int;
  19. u_short = Word;
  20. u_char = Char;
  21. u_long = Longint;
  22. const
  23. winsocket = 'WSock32.dll';
  24. SOCKET_ERROR = -1;
  25. INVALID_SOCKET = TSocket(NOT(0));
  26. WSADESCRIPTION_LEN = 256;
  27. WSASYS_STATUS_LEN = 128;
  28. AF_INET = 2;
  29. SOCK_STREAM = 1; { stream socket }
  30. SOL_SOCKET = $ffff; {options for socket level }
  31. SO_LINGER = $0080; { linger on close if data present }
  32. SO_SNDTIMEO = $1005; { send timeout }
  33. SO_RCVTIMEO = $1006; { receive timeout }
  34. WSAECONNRESET =10054;
  35. type
  36. SunB = packed record
  37. s_b1, s_b2, s_b3, s_b4: u_char;
  38. end;
  39. SunW = packed record
  40. s_w1, s_w2: u_short;
  41. end;
  42. PInAddr = ^TInAddr;
  43. in_addr = record
  44. case integer of
  45. 0: (S_un_b: SunB);
  46. 1: (S_un_w: SunW);
  47. 2: (S_addr: u_long);
  48. end;
  49. TInAddr = in_addr;
  50. PSockAddrIn = ^TSockAddrIn;
  51. sockaddr_in = record
  52. case Integer of
  53. 0: (sin_family: u_short;
  54. sin_port: u_short;
  55. sin_addr: TInAddr;
  56. sin_zero: array[0..7] of ansiChar);
  57. 1: (sa_family: u_short;
  58. sa_data: array[0..13] of ansiChar)
  59. end;
  60. TSockAddrIn = sockaddr_in;
  61. PSOCKADDR = ^TSockAddr;
  62. TSockAddr = sockaddr_in;
  63. PWSAData = ^TWSAData;
  64. WSAData = record // !!! also WSDATA
  65. wVersion: Word;
  66. wHighVersion: Word;
  67. szDescription: array[0..WSADESCRIPTION_LEN] of ansiChar;
  68. szSystemStatus: array[0..WSASYS_STATUS_LEN] of ansiChar;
  69. iMaxSockets: Word;
  70. iMaxUdpDg: Word;
  71. lpVendorInfo: PansiChar;
  72. end;
  73. TWSAData = WSAData;
  74. PHostEnt = ^THostEnt;
  75. {$EXTERNALSYM hostent}
  76. hostent = record
  77. h_name: PansiChar;
  78. h_aliases: ^PansiChar;
  79. h_addrtype: Smallint;
  80. h_length: Smallint;
  81. case Byte of
  82. 0: (h_addr_list: ^PansiChar);
  83. 1: (h_addr: ^PansiChar)
  84. end;
  85. THostEnt = hostent;
  86. //2006-04-25
  87. linger = record
  88. l_onoff: u_short;
  89. l_linger: u_short;
  90. end;
  91. timeval = record
  92. tv_sec: Longint;
  93. tv_usec: Longint;
  94. end;
  95. //************************我的 定义****************************
  96. type
  97. pSvrAddr=^stSvrAddr;
  98. stSvrAddr=packed record
  99. port:Word;
  100. case flg:byte of
  101. 0:(IP:array[0..15] of ansiChar);
  102. 1:(DN:array[0..30] of ansiChar);
  103. end;
  104. POrderHeader=^stOrderHeader;
  105. stOrderHeader=packed record
  106. uid:DWORD;
  107. Ver:DWORD;
  108. Enc:DWORD;
  109. id:DWORD;
  110. pid:DWORD;
  111. cmd:DWORD;
  112. len:DWORD;
  113. dat:pointer;
  114. end;
  115. //---------------------------------------------------------
  116. //***********************socket api***********************************
  117. function recv(s: TSocket; var Buf; len, flags: Integer): Integer; stdcall;
  118. function send(s: TSocket; var Buf; len, flags: Integer): Integer; stdcall;
  119. function connect(s: TSocket; var name: TSockAddr; namelen: Integer): Integer; stdcall;
  120. function closesocket(s: TSocket): Integer; stdcall;
  121. function WSACleanup: Integer; stdcall;
  122. function socket(af, Struct, protocol: Integer): TSocket; stdcall;
  123. function WSAStartup(wVersionRequired: word; var WSData: TWSAData): Integer; stdcall;
  124. function htons(hostshort: u_short): u_short; stdcall;
  125. function inet_addr(cp: PansiChar): u_long; stdcall; {PInAddr;} { TInAddr }
  126. function gethostbyname(name: PansiChar): PHostEnt; stdcall;
  127. function setsockopt(s: TSocket; level, optname: Integer; optval: PansiChar;
  128. optlen: Integer): Integer; stdcall;
  129. function WSAGetLastError: Integer; stdcall;
  130. //***********************windows api*************************************
  131. procedure ZeroMemory(Destination: Pointer; Length: DWORD);
  132. function wsprintf(Output: PansiChar; Format: PansiChar): Integer; stdcall;
  133. //***********************字符串函数*************************************
  134. function _wsprintf(lpOut: PansiChar; lpFmt: PansiChar; lpVars: Array of Const):Integer; assembler;
  135. //***********************我的函数*****************************************
  136. function InitAddr(sa:stSvrAddr;var addr:sockaddr_in):bool;stdcall;
  137. function HostToIP(hostName:pansiChar):in_addr;stdcall;
  138. function InitSocket(var hSocket:integer):bool;stdcall;
  139. procedure FreeSocket(var hSocket:integer);stdcall; //out
  140. function ConnectServer(var hSocket:integer;sa:stSvrAddr):bool;stdcall; //out
  141. function RecvBuf(hSocket:integer;p:pointer;len:DWORD):bool;stdcall;
  142. function SendBuf(socket:integer;p:pointer;size:DWORD):bool;stdcall;
  143. function GetLocalIP(IP:pansiChar):bool;stdcall;
  144. function RecvNon(hSocket:integer;p:pointer;len:integer):integer;stdcall;
  145. function VerifyOH(oh:stOrderHeader) :boolean;//校验包头;
  146. function formatOH(var oh:stOrderHeader) :stOrderHeader;//格式化包头;
  147. implementation
  148. //***********************windows api*************************************
  149. procedure ZeroMemory(Destination: Pointer; Length: DWORD);
  150. begin
  151. FillChar(Destination^, Length, 0);
  152. end;
  153. function wsprintf; external user32 name 'wsprintfA';
  154. //**********************socket api******************************************
  155. function recv; external winsocket name 'recv';
  156. function send; external winsocket name 'send';
  157. function connect; external winsocket name 'connect';
  158. function closesocket; external winsocket name 'closesocket';
  159. function WSACleanup; external winsocket name 'WSACleanup';
  160. function WSAStartup; external winsocket name 'WSAStartup';
  161. function socket; external winsocket name 'socket';
  162. function htons; external winsocket name 'htons';
  163. function inet_addr; external winsocket name 'inet_addr';
  164. function gethostbyname; external winsocket name 'gethostbyname';
  165. function setsockopt; external winsocket name 'setsockopt';
  166. function WSAGetLastError; external winsocket name 'WSAGetLastError';
  167. //***********************字符串函数*************************************
  168. function _wsprintf(lpOut:pansiChar;lpFmt:pansiChar;lpVars:array of const):integer;assembler;
  169. var
  170. count:integer;
  171. v1,v2:integer;
  172. asm
  173. mov v1,eax
  174. mov v2,edx
  175. mov eax,ecx
  176. mov ecx,[ebp+$08]
  177. inc ecx
  178. mov count,ecx
  179. dec ecx
  180. imul ecx,8
  181. add eax,ecx
  182. mov ecx,count
  183. @@1:
  184. mov edx,[eax]
  185. push edx
  186. sub eax,8
  187. loop @@1
  188. push v2
  189. push v1
  190. call wsprintf
  191. mov ecx,count
  192. imul ecx,4
  193. add ecx,8
  194. add esp,ecx
  195. end;
  196. //*********************我的函数****************************************
  197. function RecvNon(hSocket:integer;p:pointer;len:integer):integer;stdcall;
  198. begin
  199. result:=recv(hSocket,p^,len,0);
  200. end;
  201. function SendBuf(socket:integer;p:pointer;size:DWORD):bool;stdcall;
  202. var
  203. i,len:integer;
  204. pp:pointer;
  205. begin
  206. result:=false;
  207. len:=size;
  208. pp:=p;
  209. while len>0 do
  210. begin
  211. i:=send(socket,pp^,len,0);
  212. //if i=SOCKET_ERROR then exit; 2015-9-5
  213. if (i=SOCKET_ERROR) and (WSAGetLastError = WSAECONNRESET) then exit;
  214. len:=len-i;
  215. pp:=pointer(DWORD(pp)+DWORD(i));
  216. end;//while
  217. result:=true;
  218. end;
  219. function RecvBuf(hSocket:integer;p:pointer;len:DWORD):bool;stdcall;
  220. var
  221. err,k:integer;
  222. pp:pointer;
  223. begin
  224. result:=false;
  225. k:=len;
  226. pp:=p;
  227. while k>0 do
  228. begin
  229. err:=recv(hSocket,pp^,k,0);
  230. if (err=SOCKET_ERROR) or (err=0) then exit; //2015
  231. //if (err=SOCKET_ERROR) or (err=0) then exit;
  232. k:=k-err;
  233. pp:=pointer(dword(pp)+dword(err));
  234. end;
  235. result:=true;
  236. end;
  237. function ConnectServer(var hSocket:integer;sa:stSvrAddr):bool;stdcall;
  238. var
  239. err:integer;
  240. addr:sockaddr_in;
  241. begin
  242. result:=false;
  243. if not InitSocket(hSocket) then exit;
  244. InitAddr(sa,addr);
  245. err:=connect(hSocket,addr,sizeof(addr));//连接
  246. if err<>0 then FreeSocket(hSocket);
  247. result:=err=0;
  248. end;
  249. procedure FreeSocket(var hSocket:integer);stdcall;
  250. begin
  251. if hSocket<>0 then closesocket(hSocket);
  252. //WSACleanup();//终止WS2_32.DLL的使用
  253. hSocket:=0;
  254. end;
  255. {
  256. 功能描述:初始化Socket
  257. 入口参数:hSocket:Socket句柄
  258. 出口参数:返回值:成功创建返回True,否则返回False
  259. 创建日期:
  260. 修改记录:增加超时时间6分钟
  261. 2006-04-25
  262. Author:byc
  263. }
  264. function InitSocket(var hSocket:integer):bool;stdcall;
  265. var
  266. wsadata: TWSAData;
  267. err:integer;
  268. //t:linger;
  269. //timeout: timeval;
  270. tv:longint;
  271. begin
  272. result:=false;
  273. err:=WSAStartup($0202,wsadata);
  274. if err<>0 then
  275. begin //初始化WS2_32.DLL
  276. //showmessage('初始化ws_32.dll失败!');
  277. WSACleanup();//终止WS2_32.DLL的使用
  278. exit;
  279. end;//if
  280. hSocket:=socket(AF_INET, SOCK_STREAM, 0);
  281. //创建socket
  282. if hSocket=INVALID_SOCKET then
  283. begin
  284. //ShowMessage('创建SOCKET失败!');
  285. hSocket:=0;
  286. WSACleanup();
  287. exit;
  288. end;//if socket1=SOCKET_ERROR then
  289. {
  290. t.l_onoff:=1;
  291. t.l_linger:=0;
  292. //关闭socket后立刻释放资源
  293. err:=setsockopt(hSocket,SOL_SOCKET,SO_LINGER,@t,sizeof(t));
  294. if err=SOCKET_ERROR then
  295. begin
  296. FreeSocket(hSocket);
  297. exit;
  298. end;
  299. }
  300. //set recv and send timeout
  301. tv:=6*60*1000;
  302. //tv:=60000;//测试
  303. err:=setsockopt(hSocket,SOL_SOCKET,SO_SNDTIMEO,@tv,sizeof(timeval));
  304. if err=SOCKET_ERROR then
  305. begin
  306. FreeSocket(hSocket);
  307. exit;
  308. end;
  309. err:=setsockopt(hSocket,SOL_SOCKET,SO_RCVTIMEO,@tv,sizeof(timeval));
  310. if err=SOCKET_ERROR then
  311. begin
  312. FreeSocket(hSocket);
  313. exit;
  314. end;
  315. result:=true;
  316. end;
  317. function InitAddr(sa:stSvrAddr;var addr:sockaddr_in):bool;stdcall;
  318. begin
  319. result:=false;
  320. zeromemory(@addr,sizeof(addr));
  321. addr.sin_family:=AF_INET;
  322. addr.sin_port:=htons(sa.port);
  323. case sa.flg of
  324. 0:begin
  325. addr.sin_addr.S_addr:=inet_addr(sa.IP);
  326. end;//0
  327. 1:begin
  328. addr.sin_addr:=HostToIP(sa.DN);
  329. end;//1
  330. end;//case
  331. if addr.sin_addr.S_addr>0 then
  332. result:=true;
  333. end;
  334. function HostToIP(hostName:pansiChar):in_addr;stdcall;
  335. var
  336. hostEnt : PHostEnt;
  337. addr:pansiChar;
  338. err:integer;
  339. wd:wsadata;
  340. begin
  341. err:=WSAStartup($0202,WD);
  342. if err<>0 then exit;
  343. ZeroMemory(@result,sizeof(in_addr));
  344. hostEnt:=gethostbyname (hostName);
  345. if Assigned (hostEnt) then
  346. if Assigned (hostEnt^.h_addr_list) then
  347. begin
  348. addr := hostEnt^.h_addr_list^;
  349. if Assigned (addr) then
  350. begin
  351. result:=PInAddr(addr)^;
  352. end;// if Assigned (addr) then
  353. end;//if Assigned (hostEnt) then
  354. wsacleanup();
  355. end;
  356. function GetLocalIP(IP:pansiChar):bool;stdcall;
  357. var
  358. wd:WSAdata;
  359. err:integer;
  360. phe:PhostEnt;
  361. addr:pansiChar;
  362. b0,b1,b2,b3:byte;
  363. begin
  364. result:=false;
  365. err:=WSAStartup($101,wd);
  366. if err<>0 then begin wsaCleanup;exit;end;
  367. phe:=GetHostByName(nil);
  368. if phe=nil then begin wsaCleanup;exit;end;
  369. addr:=(phe^.h_addr)^;
  370. if addr=nil then begin wsaCleanup;exit;end;
  371. b0:=byte((addr+0)^);b1:=byte((addr+1)^);
  372. b2:=byte((addr+2)^);b3:=byte((addr+3)^);
  373. _wsprintf(IP,'%d.%d.%d.%d',[b0,b1,b2,b3]);
  374. wsaCleanup;
  375. result:=true;
  376. end;
  377. //-------------------------------------------------------------------------
  378. function VerifyOH(oh:stOrderHeader) :boolean;//校验包头;
  379. begin
  380. result:=true;
  381. if(oh.uid<>UID)then result:=false;
  382. if(oh.Ver<>VER)then result:=false;
  383. if(oh.ENC<>ENC)then result:=false;
  384. end;
  385. function formatOH(var oh:stOrderHeader) :stOrderHeader;//格式化包头;
  386. begin
  387. oh.uid:=UID;
  388. oh.Ver:=VER;
  389. oh.Enc:=ENC;
  390. oh.id:=0;
  391. oh.pid:=0;
  392. oh.cmd:=CMD_READY;
  393. oh.len:=0;
  394. oh.dat:=nil;
  395. result:=oh;
  396. end;
  397. //------------------------------------------------------------------
  398. end.

 

3、客户端主线程

  1. unit uMain;
  2. interface
  3. uses
  4. Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  5. Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ComCtrls,
  6. Vcl.FileCtrl, Vcl.ExtCtrls,strutils,system.zip,IdGlobalProtocols,
  7. uConfig,uLog,uTransFileClient,uDes2010,uFuncs, Vcl.Menus,shellapi;
  8. type
  9. TfMain = class(TForm)
  10. Panel4: TPanel;
  11. Label2: TLabel;
  12. Label1: TLabel;
  13. edtAddr: TEdit;
  14. edtPort: TEdit;
  15. btnUpload: TButton;
  16. btnDownload: TButton;
  17. btnClose: TButton;
  18. Bar1: TStatusBar;
  19. Panel2: TPanel;
  20. Drive1: TDriveComboBox;
  21. Dir1: TDirectoryListBox;
  22. Splitter1: TSplitter;
  23. Panel3: TPanel;
  24. File1: TFileListBox;
  25. edtFile: TEdit;
  26. Splitter2: TSplitter;
  27. Panel1: TPanel;
  28. Splitter3: TSplitter;
  29. ListFileInfo: TListView;
  30. memoInfo: TMemo;
  31. btnList: TButton;
  32. btnSelAll: TButton;
  33. btnDecryptFile: TButton;
  34. lbDir: TLabel;
  35. popDir: TPopupMenu;
  36. N1: TMenuItem;
  37. N2: TMenuItem;
  38. popFile: TPopupMenu;
  39. MenuItem1: TMenuItem;
  40. MenuItem2: TMenuItem;
  41. N3: TMenuItem;
  42. N4: TMenuItem;
  43. procedure btnUploadClick(Sender: TObject);
  44. procedure FormShow(Sender: TObject);
  45. procedure btnCloseClick(Sender: TObject);
  46. procedure btnDownloadClick(Sender: TObject);
  47. procedure btnListClick(Sender: TObject);
  48. procedure FormCreate(Sender: TObject);
  49. procedure btnSelAllClick(Sender: TObject);
  50. procedure ListFileInfoColumnClick(Sender: TObject; Column: TListColumn);
  51. procedure btnDecryptFileClick(Sender: TObject);
  52. procedure N1Click(Sender: TObject);
  53. procedure MenuItem1Click(Sender: TObject);
  54. procedure MenuItem2Click(Sender: TObject);
  55. procedure N3Click(Sender: TObject);
  56. procedure N4Click(Sender: TObject);
  57. procedure N2Click(Sender: TObject);
  58. private
  59. { Private declarations }
  60. procedure TransDataMsg(var msg:TMessage);message wm_TransData;
  61. procedure TryExcepts(Sender: TObject; E: Exception);
  62. procedure parseFileList();
  63. procedure AddList(filesign,filesize:string);
  64. function decryptFilename(filename:string):string;
  65. procedure decryptfile(ss:tstrings);
  66. public
  67. { Public declarations }
  68. end;
  69. var
  70. fMain: TfMain;
  71. function CustomSortProc(Item1, Item2: TListItem; ColumnIndex: integer): integer; stdcall;
  72. function cryptfile(filedir:string):ansiString;
  73. //联系QQ:39848872微信:byc6352
  74. implementation
  75. {$R *.dfm}
  76. procedure TfMain.decryptfile(ss:tstrings);
  77. const
  78. FILE_NAME_ID='x';
  79. var
  80. i:integer;
  81. filename,newfilename,newdir:string;
  82. begin
  83. for I := 0 to ss.Count-1 do
  84. begin
  85. filename:=ss[i];
  86. if(filename[length(filename)]<>FILE_NAME_ID)then continue;
  87. if(FileSizeByName(filename)=0)then
  88. begin
  89. deletefile(filename);
  90. continue;
  91. end;
  92. uFuncs.cryptfile(filename);
  93. newfilename:=leftstr(filename,length(filename)-1);
  94. newfilename:=extractfilepath(newfilename)+uDes2010.DecryStrHex(extractfilename(newfilename),uConfig.key);
  95. movefile(pchar(filename),pchar(newfilename));
  96. newdir:=leftstr(newfilename,length(newfilename)-4);
  97. if(TZipFile.IsValid(newfilename))then
  98. begin
  99. TZipFile.ExtractZipFile(newfilename, newdir);
  100. deletefile(newfilename);
  101. end else begin
  102. memoInfo.Lines.Add('解压失败:'+newfilename);
  103. //showmessage('解压失败:'+newfilename);
  104. end;
  105. //uzip.DirectoryDecompression(newdir,newfilename);
  106. end;
  107. end;
  108. //'c:\temp\0310\2'
  109. function cryptfile(filedir:string):ansiString;
  110. var
  111. filename:array[0..MAX_PATH-1] of ansiChar;
  112. filesize:array[0..31] of ansiChar;
  113. wfd:WIN32_FIND_DATAA;
  114. hFindFile:THANDLE;
  115. newfilename,newdir:ansistring;
  116. begin
  117. result:='';
  118. strcopy(filename,pansichar(ansiString(filedir)));
  119. strcat(filename,pansichar('\*'));
  120. hFindFile:=FindFirstFileA(filename,wfd);
  121. if hFindFile=INVALID_HANDLE_VALUE then exit;
  122. while(FindNextFileA(hFindFile,wfd))do
  123. begin
  124. if(wfd.cFileName[0]='.')then continue;
  125. if(wfd.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY)<>0 then continue;
  126. //uFuncs.cryptfile(filedir+'\'+wfd.cFileName);
  127. newfilename:=filedir+'\'+wfd.cFileName;
  128. newdir:=leftstr(newfilename,length(newfilename)-4);
  129. if(TZipFile.IsValid(newfilename))then
  130. begin
  131. try
  132. TZipFile.ExtractZipFile(newfilename, newdir);
  133. except
  134. fmain.memoInfo.Lines.Add('解压失败1:'+newfilename);
  135. end;
  136. deletefile(newfilename);
  137. end else begin
  138. fmain.memoInfo.Lines.Add('解压失败:'+newfilename);
  139. //showmessage('解压失败:'+newfilename);
  140. end;
  141. end;
  142. Winapi.Windows.FindClose(hFindFile);
  143. end;
  144. function TfMain.decryptFilename(filename:string):string;
  145. const
  146. FILE_NAME_ID='x';
  147. var
  148. i:integer;
  149. newfilename,newdir:string;
  150. begin
  151. result:=filename;
  152. try
  153. if(filename[length(filename)]<>FILE_NAME_ID)then exit;
  154. newfilename:=leftstr(filename,length(filename)-1);
  155. newfilename:=uDes2010.DecryStrHex(newfilename,uConfig.key);
  156. result:=newfilename;
  157. finally
  158. end;
  159. end;
  160. procedure TfMain.AddList(filesign,filesize:string);
  161. var
  162. item:tListitem;
  163. begin
  164. item:=ListFileInfo.Items.Add;
  165. item.Caption:=filesign;
  166. item.SubItems.Add(decryptFilename(filesign));
  167. item.SubItems.Add(filesize);
  168. item.SubItems.Add('');
  169. item.ImageIndex:=8;
  170. end;
  171. procedure TfMain.parseFileList();
  172. var
  173. filelist,fileinfo:tstrings;
  174. i:integer;
  175. filename,info:string;
  176. begin
  177. if gFileList='' then exit;
  178. ListFileInfo.Clear;
  179. try
  180. filelist:=tstringlist.Create;
  181. fileinfo:=tstringlist.Create;
  182. if gFileList[length(gFileList)]=';' then delete(gFileList,length(gFileList),1);
  183. if(rightstr(gFileList,2)=#13#10) then leftstr(gFileList,length(gFileList)-2);
  184. fileList.Text:=gFileList;
  185. if(fileList.Count=0)then exit;
  186. for I := 0 to fileList.Count-1 do
  187. begin
  188. info:=fileList[i];
  189. fileinfo.Delimiter:=';';
  190. fileinfo.DelimitedText:=info;
  191. AddList(fileinfo[0],fileinfo[1]);
  192. end;
  193. bar1.Panels[0].Text:='共有文件:'+inttostr(filelist.Count);
  194. finally
  195. filelist.Free;
  196. fileinfo.Free;
  197. end;
  198. end;
  199. procedure tFMain.TransDataMsg(var msg:TMessage);
  200. var
  201. threadType:TThreadType;
  202. pTF:pTransFilesInfo;
  203. localfilename,newfilename,localpath:ansiString;
  204. i:integer;
  205. begin
  206. threadType:=TThreadType(msg.WParam);
  207. case threadType of
  208. FListFile:
  209. begin
  210. //memoSms.Lines.Add(gFileList);
  211. parseFileList();
  212. ListFileInfo.CustomSort(@CustomSortProc,0);
  213. end;
  214. FTransFile:
  215. begin
  216. pTF:=pTransFilesInfo(msg.LParam);
  217. if(pTF<>nil)then
  218. begin
  219. localfilename:=pTF^.clientFile;
  220. //memoInfo.lines.add(localfilename);
  221. if(pTF^.aAPI=Fstart)then
  222. begin
  223. memoInfo.lines.add('开始传输:'+localfilename);
  224. bar1.Panels[0].Text:='开始传输:'+localfilename;
  225. end;
  226. if(pTF^.bUpLoad)then
  227. begin
  228. if pTF^.aAPI=Fsend then
  229. bar1.Panels[0].Text:='正在上传:'+inttostr(pTF^.transed)+'/'+inttostr(pTF^.FileSize);
  230. if pTF^.aAPI=Fend then
  231. begin
  232. btnList.Click();
  233. memoInfo.lines.add('上传完成:'+localfilename);
  234. bar1.Panels[0].Text:='上传完成:'+inttostr(pTF^.transed)+'/'+inttostr(pTF^.FileSize);
  235. end;
  236. end else begin
  237. i:=ptF^.threadId;
  238. if pTF^.aAPI=FRecv then
  239. begin
  240. listFileInfo.Items[i].SubItems.Strings[2]:=inttostr(pTF^.transed);
  241. bar1.Panels[0].Text:='正在下载:'+inttostr(pTF^.transed);
  242. end;
  243. if pTF^.aAPI=Fend then
  244. begin
  245. localpath:=extractfilepath(localfilename);
  246. {
  247. newfilename:=localpath+decryptFilename(extractfilename(localfilename));
  248. if(newfilename<>localfilename)then
  249. begin
  250. renamefile(localfilename,newfilename);
  251. uFuncs.cryptfile(newfilename);
  252. end;
  253. }
  254. memoInfo.lines.add('下载完成:'+localfilename);
  255. bar1.Panels[0].Text:='下载完成:'+inttostr(pTF^.transed);
  256. listFileInfo.Items[i].SubItems.Strings[2]:='下载完成'+inttostr(pTF^.transed);
  257. file1.Update;
  258. end;
  259. end;
  260. //loadfile(localfilename);
  261. end;
  262. end;
  263. end;
  264. end;
  265. procedure TfMain.TryExcepts(Sender: TObject; E: Exception);
  266. begin
  267. Log(E.Message);
  268. //memoINfo.Lines.Add(Log(E.Message));
  269. //Log(
  270. end;
  271. procedure TfMain.btnCloseClick(Sender: TObject);
  272. begin
  273. close;
  274. end;
  275. procedure TfMain.btnDownloadClick(Sender: TObject);
  276. var
  277. localFilename,remoteFilename:string;
  278. i:integer;
  279. begin
  280. if(ListFileInfo.SelCount=0)then
  281. begin
  282. showmessage('请选择要下载的文件!');
  283. exit;
  284. end;
  285. for I := 0 to ListFileInfo.Items.Count-1 do
  286. begin
  287. if(ListFileInfo.Items[i].Selected)then
  288. begin
  289. remoteFilename:=ListFileInfo.Items[i].Caption;
  290. localFilename:=file1.Directory+'\'+remoteFilename;
  291. uTransFileClient.downloadFile(localFilename,remoteFilename,i);
  292. end;
  293. end;
  294. end;
  295. procedure TfMain.btnListClick(Sender: TObject);
  296. begin
  297. uTransFileClient.ProcessListFile();
  298. end;
  299. procedure TfMain.btnSelAllClick(Sender: TObject);
  300. begin
  301. ListFileInfo.SelectAll;
  302. end;
  303. procedure TfMain.btnDecryptFileClick(Sender: TObject);
  304. begin
  305. //cryptfile('c:\temp\0310\2');
  306. decryptfile(file1.Items);
  307. dir1.Update;
  308. file1.Update;
  309. bar1.Panels[1].Text:=''+inttostr(file1.Items.Count)+'个文件';
  310. end;
  311. procedure TfMain.btnUploadClick(Sender: TObject);
  312. var
  313. localFilename,remoteFilename:string;
  314. i:integer;
  315. begin
  316. if(file1.SelCount=0)then
  317. begin
  318. showmessage('请选择要上传的文件!');
  319. exit;
  320. end;
  321. for i := 0 to file1.Count-1 do
  322. begin
  323. if(file1.Selected[i])then
  324. begin
  325. localFilename:=file1.Items[i];
  326. remoteFilename:=extractfilename(localFilename);
  327. uTransFileClient.uploadFile(localFilename,remoteFilename);
  328. end;
  329. end;
  330. //localFilename:=file1.FileName;
  331. //remoteFilename:=extractfilename(localFilename);
  332. //uTransFileClient.uploadFile(localFilename,remoteFilename);
  333. end;
  334. procedure TfMain.FormCreate(Sender: TObject);
  335. begin
  336. application.OnException:=TryExcepts;
  337. end;
  338. procedure TfMain.FormShow(Sender: TObject);
  339. begin
  340. //fmain.Caption:=uConfig.APP_NAME+uConfig.APP_VERSION+uConfig.APP_CONTACT;
  341. fmain.Caption:=uConfig.APP_NAME+uConfig.APP_VERSION;
  342. edtAddr.Text:=uConfig.FTS_HOST_FORGED;
  343. edtPort.Text:=inttostr(uConfig.FTS_PORT);
  344. uTransFileClient.hForm:=fmain.Handle;
  345. btnList.Click();
  346. dir1.Drive:='c';
  347. dir1.Directory:='c:\temp';
  348. end;
  349. procedure TfMain.ListFileInfoColumnClick(Sender: TObject; Column: TListColumn);
  350. begin
  351. ListFileInfo.CustomSort(@CustomSortProc,Column.Index);
  352. end;
  353. procedure TfMain.MenuItem1Click(Sender: TObject);
  354. var
  355. filename:string;
  356. begin
  357. if File1.Count=0 then exit;
  358. if File1.ItemIndex=-1 then exit;
  359. filename:=File1.Items[File1.ItemIndex];
  360. ShellExecute(Handle,pchar('open'), pchar('explorer.exe'), pchar('/select,'+filename), nil, SW_SHOW);
  361. end;
  362. procedure TfMain.MenuItem2Click(Sender: TObject);
  363. var
  364. filename:string;
  365. begin
  366. if File1.Count=0 then exit;
  367. if File1.ItemIndex=-1 then exit;
  368. filename:=File1.Items[File1.ItemIndex];
  369. ShellExecute(Handle,pchar('open'), pchar('explorer.exe'), pchar(filename), nil, SW_SHOW);
  370. end;
  371. procedure TfMain.N1Click(Sender: TObject);
  372. var
  373. dir,dirname:string;
  374. begin
  375. dir:=dir1.Directory;
  376. dirname:= InputBox('请输入目录名:','目录名:','');//参数分别为标题,提示,默认值
  377. if dirname<>'' then
  378. begin
  379. ForceDirectories(dir+'\'+dirname);
  380. dir1.Update;
  381. end;
  382. end;
  383. procedure TfMain.N2Click(Sender: TObject);
  384. var
  385. dir:string;
  386. begin
  387. if dir1.Count=0 then exit;
  388. if dir1.ItemIndex=-1 then exit;
  389. dir:=dir1.Items[File1.ItemIndex];
  390. uFuncs.deldir(dir) ;
  391. dir1.Update;
  392. end;
  393. procedure TfMain.N3Click(Sender: TObject);
  394. var
  395. filename,newfilename:string;
  396. begin
  397. if File1.Count=0 then exit;
  398. if File1.ItemIndex=-1 then exit;
  399. filename:=File1.Items[File1.ItemIndex];
  400. newfilename:= InputBox('请输入文件名:','文件名:','');//参数分别为标题,提示,默认值
  401. if newfilename<>'' then
  402. begin
  403. movefile(pchar(filename),pchar(newfilename));
  404. File1.Update;
  405. end;
  406. end;
  407. procedure TfMain.N4Click(Sender: TObject);
  408. var
  409. filename:string;
  410. begin
  411. if File1.Count=0 then exit;
  412. if File1.ItemIndex=-1 then exit;
  413. filename:=File1.Items[File1.ItemIndex];
  414. deletefile(filename);
  415. file1.Update;
  416. end;
  417. function CustomSortProc(Item1, Item2: TListItem; ColumnIndex: integer): integer; stdcall;
  418. begin
  419. if ColumnIndex = 0 then
  420. Result := CompareText(Item1.Caption,Item2.Caption)
  421. else
  422. Result := CompareText(Item1.SubItems[ColumnIndex-1],Item2.SubItems[ColumnIndex-1])
  423. end;
  424. end.

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/盐析白兔/article/detail/142706
推荐阅读
相关标签
  

闽ICP备14008679号