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

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

一、服务器端

unit uTransFileSrv;

interface
uses winsock,windows,graphics,classes,uStr,uFuncs,system.zip,uConfig;
const
  wm_user=$0400;
  wm_TransData=wm_user+100+1;
  MAXBUF=8192;
  MAXPATH=260;

  UID:integer=8888;//包头标识;
  VER:integer=1002;
  ENC:integer=7620;

  CMD_READY:integer=1001;//准备好命令;
  CMD_FILE_LIST=4001;//列举目录;传递绝对路径;
  CMD_FILE_TRANS=4002;//文件传输
  CMD_FILE_DEL=4003;//删除文件
type
  POrderHeader=^stOrderHeader;
  stOrderHeader=packed record
    uid:DWORD;
    Ver:DWORD;
    Enc:DWORD;
    id:DWORD;
    pid:DWORD;
    cmd:DWORD;
    len:DWORD;
    dat:pointer;
  end;

  TThreadType=(FTransFile,FGetRet,FTypeClient,FListenSocket,FMainThread,FTransfer,FTransferMain,FRecvData,FListFile );
  Torder=(FStart,Fclose);
  TAPIFlag=(FWSAStartup,Fsocket,Fsetsockopt,Fbind,Flisten,Faccept,Frecv,FcreateFile,FGetFileSize,Fsend,FRecv2,
            FWriteFile,FSetFilePointer,Frecv_S,FSetFilePointer_S,FReadFile_S,FReadFile_S1,Fsend_S,Fcreatethread,
            FGetFileAttributes,FDirectoryCompression,FDirectoryCompression_1,FDirectoryDecompression_1,FDirectoryDecompression,
            Fdeletefile,FRecv3,FCreateDIBSection,FNull,FthreadStart,FthreadEnd,Fverify,FPackageEnd);
  TAPIType=(Fwindows,Fsock);
  TRequestType=(RTransFile,RListFile,RRecvData);
  pSocket=^stSocket;
  stSocket=packed record
    socketHandle:tsocket;
    addr:tsockaddr;
    addrLen:integer;
  end;
  pRunAPIInfo=^stRunAPIInfo;
  stRunAPIInfo=packed record
    aAPI:TAPIFlag;
    APIType:TAPIType;
    result:integer;
    errCode:integer;
    Info:array[0..1023] of ansiChar;
  end;
  pTransRate=^stTransRate;
  stTransRate=packed record
    Transed:cardinal;
    TransedHigh:cardinal;
    Speed:int64;
  end;
  pFileInfo=^stFileInfo;
  stFileInfo=packed record
    hFile:cardinal;
    isUpLoad:bool;
    FileName:array[0..MAXPATH-1] of ansiChar;
    FileSize:cardinal;
    FileSizeHigh:cardinal;
    ClientFileSize:cardinal;
    ClientFileSizeHigh:cardinal;
  end;
  pSendMsgTo=^stSendMsgTo;
  stSendMsgTo=packed record
    hform:hwnd;
    msgType:cardinal;
  end;
  pThreadInfo=^stThreadInfo;
  stThreadInfo=packed record
    threadType:TThreadType;
    active:bool;
    hThread:cardinal;
    threadID:cardinal;
  end;
  pMainTread=^stMainTread;
  stMainTread=packed record
    threadType:TThreadType;
    order:Torder;
    num:integer;
  end;
  pListenSocket=^stListenSocket;
  stListenSocket=packed record
    thread:stThreadInfo;
    runAPI:stRunAPIInfo;
    sendMsg:stSendMsgTo;
    socket:stSocket;
    wsadata: TWSAData;
    port:DWORD;
    num:integer;
  end;
  pTypeCS=^stTypeCS;
  stTypeCS=packed record
    thread:stThreadInfo;
    runAPI:stRunAPIInfo;
    sendMsg:stSendMsgTo;
    socket:stSocket;
    TransType:TThreadType;
    oh:stOrderHeader;
    num:integer;
  end;
  pTransFilesCS=^stTransFilesCS;
  stTransFilesCS=packed record
    thread:stThreadInfo;
    runAPI:stRunAPIInfo;
    sendMsg:stSendMsgTo;
    socket:stSocket;
    fileInfo:stFileInfo;
    transRate:stTransRate;
  end;
  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;
  stRequestFileInfo=packed record
    fileName:array[0..MAXPATH-1] of ansiChar;
    bUpLoad:bool;
  end;//
  pTransFilesInfo=^stTransFilesInfo;
  stTransFilesInfo=packed record
    clientFile:array[0..MAX_PATH-1] of ansiChar;
    serverFile:array[0..MAX_PATH-1] of ansiChar;
    iRootDir:DWORD;
    bUpLoad:bool;
    bFolder:bool;
    bCompleteDel:bool;
  end;
  pRecvDataCS=^stRecvDataCS;
  stRecvDataCS=packed record
    thread:stThreadInfo;
    runAPI:stRunAPIInfo;
    sendMsg:stSendMsgTo;
    socket:stSocket;
    oh:stOrderHeader;
    transRate:stTransRate;
    num:integer;
    data:pointer;
    dataSize:integer;
  end;
  pListFileCS=^stListFileCS;
  stListFileCS=packed record
    thread:stThreadInfo;
    runAPI:stRunAPIInfo;
    sendMsg:stSendMsgTo;
    socket:stSocket;
    oh:stOrderHeader;
    transRate:stTransRate;
    num:integer;
    filename:array[0..MAX_PATH-1] of ansiChar;
  end;


function VerifyOH(oh:stOrderHeader) :boolean;//校验包头;
function formatOH(var oh:stOrderHeader) :stOrderHeader;//格式化包头;

procedure TransDataThread(pLisenSocketInfo:pointer);stdcall;
//function RunAPIOK(pThreadDataInfo:pointer):bool;stdcall;
procedure GetAPIErrCode(pRun:pRunAPIInfo);stdcall;
procedure TransTypeThread(pClientSocketInfo:pointer);stdcall;
procedure TransDirThread(pTransFilesInfo:pointer);stdcall;
function TransDirAPI(pTransFilesInfo:pointer;FAPI:tAPIFlag):bool;stdcall;
procedure TransFileThread(pTransFileInfo:pointer);stdcall;
function TransFileAPI(pTransFileInfo:pointer;FAPI:tAPIFlag):bool;stdcall;
function TransTypeAPI(pTransTypeInfo:pointer;FAPI:tAPIFlag):bool;stdcall;
function TransDataAPI(pLisenSocketInfo:pointer;FAPI:TAPIFlag):bool;stdcall;
procedure RecvDataThread(pRecvInfo:pointer);stdcall;
function RecvDataAPI(pRcvDataInfo:pointer;FAPI:tAPIFlag):bool;stdcall;
procedure ListFileThread(pListInfo:pointer);stdcall;
function ListFileAPI(pListInfo:pointer;FAPI:tAPIFlag):bool;stdcall;
function getListFileInfo():ansiString;
var
  workdir,upDir,downDir:ansiString;
  pDatas:tlist;

implementation

function getListFileInfo():ansiString;
var
  filename:array[0..MAX_PATH-1] of ansiChar;
  filesize:array[0..31] of ansiChar;
  wfd:WIN32_FIND_DATAA;
  hFindFile:THANDLE;
  //fa:ansiChar;
begin
  result:='';
  strcopy(filename,pansichar(ansiString(uConfig.updir)));
  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;
    inttostr(wfd.nFileSizeLow,filesize);
    result:=result+wfd.cFileName+';'+filesize+#13#10;
  end;
  Windows.FindClose(hFindFile);
end;

procedure ListFileThread(pListInfo:pointer);stdcall;

var
  pData:pListFileCS;
  len,i:cardinal;
  fileList:ansiString;
begin
  pData:=pListInfo;
  ListFileAPI(pData,FthreadStart);
try
  fileList:=getListFileInfo();
  len:=length(fileList);
  if(len=0)then exit;
  pdata^.oh.len:=len;
  pData^.runAPI.result:=send(pData^.socket.socketHandle,pdata^.oh,sizeof(stOrderHeader),0);
  if not ListFileAPI(pData,Fsend) then exit;
  i:=1;
  pData^.runAPI.result:=0;
  while len>0 do
  begin
    pData^.runAPI.result:=send(pData^.socket.socketHandle,fileList[i],len,0);
    if not ListFileAPI(pData,Fsend) then exit;
    i:=i+pData^.runAPI.result;
    len:=len-pData^.runAPI.result;
  end;
finally
  ListFileAPI(pData,FthreadEnd);
  //sendMessage(pData^.sendMsg.hform,pData^.sendMsg.msgType,0,integer(pData));
end;
end;
function ListFileAPI(pListInfo:pointer;FAPI:tAPIFlag):bool;stdcall;
label 1;
var
  pData:pListFileCS;
  pRun:pRunAPIInfo;
  pThreadDataInfo:pThreadInfo;
  pSock:pSocket;
  pMsg:pSendMsgTo;
begin
  result:=true;
  pThreadDataInfo:=pListInfo;
  pData:=pListInfo;
  pRun:=pRunAPIInfo(pansiChar(pData)+sizeof(stThreadInfo));
  pMsg:=pSendMsgTo(pansiChar(pData)+sizeof(stThreadInfo)+sizeof(stRunAPIInfo));
  pSock:=pSocket(pansiChar(pData)+sizeof(stThreadInfo)+sizeof(stRunAPIInfo)+sizeof(stSendMsgTo));
  pRun^.aAPI:=FAPI;
  case pData^.runAPI.aAPI of
  FthreadStart:
    begin
      pRun^.APIType:=Fwindows;
      strcopy(pRun^.Info,'列文件线程开始!');
      SendMessage(pMsg^.hform,pMsg^.msgType,0,integer(pData));
      exit;
    end;
  Fsend:
    begin
      pRun^.APIType:=Fsock;
      if pRun^.result<>SOCKET_ERROR then exit;
      strcopy(pRun^.Info,'发送数据失败!');
    end;//Fsend
  FthreadEnd:
    begin
      pRun^.APIType:=Fwindows;
      strcopy(pRun^.Info,'列文件线程结束!');
      SendMessage(pMsg^.hform,pMsg^.msgType,1,integer(pData));
      goto 1;
    end;
  end;//case
  GetAPIErrCode(pRun);
  SendMessage(pMsg^.hform,pMsg^.msgType,0,integer(pData));
  result:=false;
1:
  closesocket(pSock^.socketHandle);
  pThreadDataInfo^.active:=false;
  if (pData^.oh.Dat<>nil) then begin freemem(pData^.oh.Dat);pData^.oh.Dat:=nil;end;
  dispose(pData);
end;




procedure TransDataThread(pLisenSocketInfo:pointer);stdcall;
var
  flag:bool;
  pData:pListenSocket;
  pClient:pTypeCS;
begin
  with pData^.runAPI,pData^.socket do
  begin
    pData:=pLisenSocketInfo;
    TransDataAPI(pData,FthreadStart);
    pData^.runAPI.result:=WSAStartup($0202,pData^.wsadata);
    if not TransDataAPI(pData,FWSAStartup) then exit;

    pData^.runAPI.result:=socket(AF_INET, SOCK_STREAM, 0); //SOCK_DGRAM
    if not TransDataAPI(pData,Fsocket) then exit;
    pData^.socket.socketHandle:=pData^.runAPI.result;

    pData^.runAPI.result:=setsockopt(pData^.socket.socketHandle,SOL_SOCKET,SO_REUSEADDR,@flag,sizeof(flag));
    if not TransDataAPI(pData,Fsetsockopt) then exit;

    zeromemory(@(pData^.socket.addr),sizeof(pData^.socket.addr));
    pData^.socket.addr.sin_family:=AF_INET;
    pData^.socket.addr.sin_port:=htons(pData^.PORT);
    pData^.socket.addr.sin_addr.s_addr:=htonl(INADDR_ANY);

    pData^.runAPI.result:=bind(pData^.socket.socketHandle,pData^.socket.addr,sizeof(pData^.socket.addr));
    if not TransDataAPI(pData,Fbind) then exit;
    pData^.runAPI.result:=listen(pData^.socket.socketHandle,5);
    if not TransDataAPI(pData,Flisten) then exit;
  end;//with
  while true do
  begin
    new(pClient);
    pClient^.thread.active:=true;
    pClient^.thread.threadType:=FTypeClient;
    pClient^.sendMsg.hform:=pData^.sendMsg.hform;
    pClient^.sendMsg.msgType:=pData^.sendMsg.msgType;
    zeromemory(@(pClient^.socket.Addr),sizeof(pClient^.socket.addr));
    pClient^.socket.AddrLen:=sizeof(pClient^.socket.addr);
    pClient^.num:=pData^.num;
    //pClient^.socket.socketHandle:=Accept(pData^.socket.socketHandle,@(pClient^.socket.Addr),@(pClient^.socket.AddrLen));
    pData^.runAPI.result:=Accept(pData^.socket.socketHandle,@(pClient^.socket.Addr),@(pClient^.socket.AddrLen));
    if not TransDataAPI(pData,Faccept) then
    begin
      dispose(pClient);
      if pData^.runAPI.errCode=WSAENOTSOCK then
      begin
        pData^.thread.active:=false;
        closesocket(pData^.socket.socketHandle);
        WSACleanup();
        dispose(pData);
        exit;
      end
      else begin
        continue;
      end;//if
    end;
    pClient^.socket.socketHandle:=pData^.runAPI.result;
    pData^.runAPI.result:=createthread(nil,0,@TransTypeThread,pClient,0,pClient^.thread.threadID);
    if not TransDataAPI(pData,Fcreatethread) then
    begin
      dispose(pClient);
      continue;
    end;
    pClient^.thread.hThread:=pData^.runAPI.result;
  end;//while
end;


function TransDataAPI(pLisenSocketInfo:pointer;FAPI:TAPIFlag):bool;stdcall;
var
  pData:pListenSocket;
  pRun:pRunAPIInfo;
  pThreadDataInfo:pThreadInfo;
  pSock:pSocket;
  pMsg:pSendMsgTo;
begin
  result:=true;
  pThreadDataInfo:=pLisenSocketInfo;
  pData:=pLisenSocketInfo;
  pRun:=pRunAPIInfo(pansiChar(pData)+sizeof(stThreadInfo));
  pMsg:=pSendMsgTo(pansiChar(pData)+sizeof(stThreadInfo)+sizeof(stRunAPIInfo));
  pSock:=pSocket(pansiChar(pData)+sizeof(stThreadInfo)+sizeof(stRunAPIInfo)+sizeof(stSendMsgTo));
  pRun^.aAPI:=FAPI;
  case pRun^.aAPI of
  FthreadStart:
    begin
      pRun^.APIType:=Fwindows;
      strcopy(pRun^.Info,'主线程开始!');
      SendMessage(pMsg^.hform,pMsg^.msgType,0,integer(pData));
      exit;
    end;
  FWSAStartup:
    begin
      pRun^.APIType:=Fsock;
      if  pRun^.result=0 then exit;
      strcopy(pRun^.Info,'初始化WS2_32.DLL失败!错误代码是:');
    end;//FWSAStartup
  Fsocket:
    begin
      pRun^.APIType:=Fsock;
      if pRun^.result<>INVALID_SOCKET then
      begin
        strcopy(pRun^.Info,'创建侦听socket!');
        SendMessage(pMsg^.hform,pMsg^.msgType,0,integer(pData));
        exit;
      end;
      strcopy(pRun^.Info,'创建socket失败!!错误代码是:');
    end;//Fsocket
  Fsetsockopt:
    begin
      pRun^.APIType:=Fsock;
      if pRun^.result<>SOCKET_ERROR then exit;
      strcopy(pRun^.Info,'setsockopt失败!错误代码是:');
    end;//Fsetsockopt
  Fbind:
    begin
      pRun^.APIType:=Fsock;
      if pRun^.result<>SOCKET_ERROR then exit;
      strcopy(pRun^.Info,'绑定socket失败!错误代码是:');
    end;//Fbind
  Flisten:
    begin
      pRun^.APIType:=Fsock;
      if pRun^.result<>SOCKET_ERROR then
      begin
        strcopy(pRun^.Info,'服务处于等待中...');
        SendMessage(pMsg^.hform,pMsg^.msgType,0,integer(pData));
        exit;
      end;
      strcopy(pRun^.Info,'侦听端口失败!错误代码是:');
    end;//Flisten
  Faccept:
    begin
      pRun^.APIType:=Fsock;
      if pRun^.result<>INVALID_SOCKET then exit;
      strcopy(pRun^.Info,'接受连接失败!错误代码是:');
      GetAPIErrCode(pRun);
      SendMessage(pMsg^.hform,pMsg^.msgType,0,integer(pData));
      exit;
    end;//Faccept
  FcreateThread:
    begin
      pRun^.APIType:=Fwindows;
      if pRun^.result<>0 then exit;
      strcopy(pRun^.Info,'创建线程失败!错误代码是:');
      GetAPIErrCode(pRun);
      SendMessage(pMsg^.hform,pMsg^.msgType,0,integer(pData));
      exit;
    end;//
  end;//case
  GetAPIErrCode(pRun);
  pThreadDataInfo^.active:=false;
  closesocket(pSock^.socketHandle);
  WSACleanup();
  SendMessage(pMsg^.hform,pMsg^.msgType,0,integer(pData));
  dispose(pData);
  result:=false;
end;



procedure TransTypeThread(pClientSocketInfo:pointer);stdcall;
var
  pData:pTypeCS;
  bTransType:TRequestType;
  pTF:pTransFilesCS;
  pRD:pRecvDataCS;
  pLF:pListFileCS;
begin
  pData:=pClientSocketInfo;
  TransTypeAPI(pData,FthreadStart);
  pData^.runAPI.result:=Recv(pData^.socket.socketHandle,pData^.oh,sizeof(stOrderHeader),0);
  if not TransTypeAPI(pData,Frecv) then exit;
    //verify connect  validity:
  if not TransTypeAPI(pData,Fverify) then exit;


  if pData^.oh.cmd=CMD_FILE_TRANS then bTransType:=RTransFile
  else if pData^.oh.cmd=CMD_FILE_LIST then bTransType:=RListFile
  else bTransType:=RRecvData;

  case bTransType of
  RTransFile:
    begin
      new(pTF);
      pTF^.thread.threadType:=FTransFile;
      pTF^.sendMsg:=pData^.sendMsg;
      pTF^.socket:=pData^.socket;
      pTF^.thread.active:=true;

      pData^.TransType:=pTF^.thread.threadType;
      pData^.runAPI.result:=createthread(nil,0,@TransDirThread,pTF,0,pTF^.thread.threadID);
      if not TransTypeAPI(pData,Fcreatethread) then
      begin
        dispose(pTF);
        exit;
      end;
      pTF^.thread.hThread:=pData^.runAPI.result;
    end;
       RListFile:
    begin
      new(pLF);
      zeromemory(pLF,sizeof(stListFileCS));
      pLF^.thread.threadType:=FListFile;
      pLF^.sendMsg:=pData^.sendMsg;
      pLF^.socket:=pData^.socket;
      pLF^.thread.active:=true;
      pLF^.oh:=pData^.oh;
      pLF^.num:=pData^.num;
      pData^.TransType:=pLF^.thread.threadType;
      pData^.runAPI.result:=createthread(nil,0,@ListFileThread,pLF,0,pLF^.thread.threadID);
      if not TransTypeAPI(pData,Fcreatethread) then
      begin
        dispose(pLF);
        exit;
      end;
      pLF^.thread.hThread:=pData^.runAPI.result;
    end;
    RRecvData:
    begin
      new(pRD);
      zeromemory(pRD,sizeof(stRecvDataCS));
      pRD^.thread.threadType:=FRecvData;
      pRD^.sendMsg:=pData^.sendMsg;
      pRD^.socket:=pData^.socket;
      pRD^.thread.active:=true;
      pRD^.oh:=pData^.oh;
      pRD^.num:=pData^.num;
      pData^.TransType:=pRD^.thread.threadType;
      pData^.runAPI.result:=createthread(nil,0,@RecvDataThread,pRD,0,pRD^.thread.threadID);
      if not TransTypeAPI(pData,Fcreatethread) then
      begin
        dispose(pRD);
        exit;
      end;
      pRD^.thread.hThread:=pData^.runAPI.result;
    end;//RTransData
  end;//case
  TransTypeAPI(pData,FthreadEnd);

end;


function TransTypeAPI(pTransTypeInfo:pointer;FAPI:tAPIFlag):bool;stdcall;
var
  pData:pTypeCS;
  pRun:pRunAPIInfo;
  pSock:pSocket;
  pMsg:pSendMsgTo;
begin
  result:=true;
  pData:=pTransTypeInfo;
  pRun:=pRunAPIInfo(pansiChar(pData)+sizeof(stThreadInfo));
  pMsg:=pSendMsgTo(pansiChar(pData)+sizeof(stThreadInfo)+sizeof(stRunAPIInfo));
  pSock:=pSocket(pansiChar(pData)+sizeof(stThreadInfo)+sizeof(stRunAPIInfo)+sizeof(stSendMsgTo));
  pData^.runAPI.aAPI:=FAPI;
  pData^.runAPI.APIType:=Fsock;
  case pData^.runAPI.aAPI of
  FthreadStart:
    begin
      pRun^.APIType:=Fwindows;
      strcopy(pRun^.Info,'识别线程开始!');
      SendMessage(pMsg^.hform,pMsg^.msgType,0,integer(pData));
      exit;
    end;
  FRecv:
    begin
      pData^.runAPI.APIType:=Fsock;
      if (pData^.runAPI.result<>SOCKET_ERROR) and (pData^.runAPI.result<>0) then exit; //
      if  pData^.runAPI.result=SOCKET_ERROR then
        strcopy(pData^.runAPI.Info,'接收命令数据失败!错误代码是:');
      if  pData^.runAPI.result=0 then
        strcopy(pData^.runAPI.Info,'接收命令数据失败!Recv返回0!可能的错误是:');
    end;
  Fverify:
    begin
      pRun^.APIType:=Fwindows;
      if (VerifyOH(pData^.oh)) then
      begin
        strcopy(pRun^.Info,'数据端连接验证成功!');
        SendMessage(pMsg^.hform,pMsg^.msgType,0,integer(pData));
        exit;
      end//if pData^.oh.Version=con_CON_VER and pData^.oh.Encrpt=con_Encrpt then
      else begin
        strcopy(pData^.runAPI.Info,'数据端连接验证失败!');
        //SendMessage(pMsg^.hform,pMsg^.msgType,0,integer(pData));
        //closesocket(pSock^.socketHandle);
        //exit;
      end;//if pData^.oh.Version=con_CON_VER and pData^.oh.Encrpt=con_Encrpt then
    end;//Fverify
  FcreateThread:
    begin
      pData^.runAPI.APIType:=FWindows;
      if prun^.result<>0 then
      begin
        case pData^.TransType of
        FTypeClient:
          begin
            strcopy(pRun^.Info,'创建服务识别线程..!');
          end;//FTypeClient
        FTransFile:
          begin
           strcopy(pRun^.Info,'创建文件传输线程..!');
          end;//FTransFile
        FRecvData:
          begin
           strcopy(pRun^.Info,'创建数据传输线程..!');
          end;//FTransFile
        end;//case
        //sendmessage(pMsg^.hform,pMsg^.msgType,0,integer(pData));
        exit;
      end;//if
      strcopy(pRun^.Info,'创建线程失败!错误代码是:');
    end;//FcreateThread
  FthreadEnd:
    begin
      pData^.runAPI.APIType:=FWindows;
      pData^.runAPI.Info:='服务识别线程正常终止!';
    end;//end
  end;//case
  GetAPIErrCode(pRun);
  if pData^.runAPI.aAPI<>FthreadEnd then
    closesocket(pSock^.socketHandle);
  pData^.thread.active:=false;
  SendMessage(pMsg^.hform,pMsg^.msgType,0,integer(pData));
  dispose(pData);
  result:=false;
end;


function TransDirAPI(pTransFilesInfo:pointer;FAPI:tAPIFlag):bool;stdcall;
var
  pdata:pTransFilesCS;
  pRun:pRunAPIInfo;
  pThreadDataInfo:pThreadInfo;
  pSock:pSocket;
  pMsg:pSendMsgTo;
  pFile:pFileInfo;
begin
  result:=true;
  pdata:=pTransFilesInfo;
  pThreadDataInfo:=pTransFilesInfo;
  pRun:=pRunAPIInfo(pansiChar(pData)+sizeof(stThreadInfo));
  pMsg:=pSendMsgTo(pansiChar(pData)+sizeof(stThreadInfo)+sizeof(stRunAPIInfo));
  pSock:=pSocket(pansiChar(pData)+sizeof(stThreadInfo)+sizeof(stRunAPIInfo)+sizeof(stSendMsgTo));
  pFile:=pFileInfo(pansiChar(pData)+sizeof(stThreadInfo)+sizeof(stRunAPIInfo)+sizeof(stSendMsgTo)+sizeof(stSocket));
  pRun^.aAPI:=FAPI;
  case pRun^.aAPI of
  FthreadStart:
    begin
      pRun^.APIType:=Fwindows;
      strcopy(pRun^.Info,'文件传输线程开始!');
      SendMessage(pMsg^.hform,pMsg^.msgType,0,integer(pData));
      exit;
    end;
  Frecv:
    begin
      pRun^.APIType:=Fsock;
      if pRun^.result<>SOCKET_ERROR then exit;
      strcopy(pRun^.Info,'接收数据失败!错误代码是:');
    end;//Frecv
  FDirectoryCompression_1:
    begin
      pRun^.APIType:=Fwindows;
      strcopy(pRun^.Info,'开始压缩文件..!');
      strcat(pRun^.Info,pFile^.fileName);
      SendMessage(pMsg^.hform,pMsg^.msgType,0,integer(pData));
      exit;
    end;
  FDirectoryCompression:
    begin
      pRun^.APIType:=Fwindows;
      if pRun^.result>0 then
      begin
        strcopy(pRun^.Info,'压缩文件完成!');
        strcat(pRun^.Info,pFile^.fileName);
        SendMessage(pMsg^.hform,pMsg^.msgType,0,integer(pData));
        exit;
      end
      else begin
        strcopy(pRun^.Info,'压缩文件失败!');
        strcat(pRun^.Info,pFile^.fileName);
      end;
    end;//FDirectoryCompression
    FcreateFile:
      begin
        pRun^.APIType:=Fwindows;
        if (pRun^.result<>-1) then exit;
        strcopy(pRun^.Info,'创建文件失败!错误代码是:');
      end;//FcreateFile:
  FGetFileSize:
    begin
      pRun^.APIType:=Fwindows;
      if pRun^.result<>-1 then exit;
      if (pRun^.result=-1) and (GetLastError()=NO_ERROR) then exit;
      strcopy(pRun^.Info,'获取文件大小失败!');
    end;//FGetFileSize
  FSetFilePointer:
    begin
      pRun^.APIType:=Fwindows;
      if pRun^.result<>-1 then exit;
      strcopy(pRun^.Info,'设置文件位置失败!!');
    end;//FSetFilePointer
  Fsend:
    begin
      pRun^.APIType:=Fsock;
      if pRun^.result<>SOCKET_ERROR then exit;
      strcopy(pRun^.Info,'发送数据失败!');
    end;//Fsend
  Frecv2:
    begin
      pRun^.APIType:=Fsock;
      if (pRun^.result<>INVALID_SOCKET) and (pRun^.result<>0) then exit;
      if pRun^.result=SOCKET_ERROR then
      begin
        strcopy(pRun^.Info,'接收文件数据失败!');
        GetAPIErrCode(pRun);
      end;
      if pRun^.result=0 then
        strcopy(pRun^.Info,'文件接收完成!');
        strcat(pRun^.Info,pFile^.FileName);
    end; //Frecv2
  FWriteFile:
    begin
      pRun^.APIType:=Fwindows;
      if pRun^.result=1 then exit;
      strcopy(pRun^.Info,'写文件失败!');
    end;//Fwritefile
  Frecv_S:
    begin
      pRun^.APIType:=Fsock;
      if pRun^.result=4 then exit;
      strcopy(pRun^.Info,'接收文件大小失败!(发送文件)');
    end;//Frecv_S
  FSetFilePointer_S:
    begin
      pRun^.APIType:=Fwindows;
      if pRun^.result<>-1 then exit;
      strcopy(pRun^.Info,'设置文件位置失败!(发送文件)');
    end;//FSetFilePointer_S
  FReadFile_S:
    begin
      pRun^.APIType:=Fwindows;
      if pRun^.result=1 then exit;
      strcopy(pRun^.Info,'读文件失败!(发送文件)');
    end;//Freadfile_s
  FReadFile_S1:
    begin
      pRun^.APIType:=Fwindows;
      if pRun^.result>0 then exit;
      strcopy(pRun^.Info,'发送文件完成!(发送文件)');
      strcat(pRun^.Info,pFile^.fileName);
    end;//Freadfile_s1
  Fsend_S:
    begin
      pRun^.APIType:=Fwindows;
      if pRun^.result<>SOCKET_ERROR then exit;
      strcopy(pRun^.Info,'发送数据失败!(发送文件)');
    end;
  FGetFileAttributes:
    begin
      pRun^.APIType:=Fwindows;
      if pRun^.result<>-1 then exit;
      strcopy(pRun^.Info,'获取文件属性失败!');
    end;
  FDirectoryDecompression_1:
    begin
      pRun^.APIType:=Fwindows;
      strcopy(pRun^.Info,'开始解压缩文件..!');
      strcat(pRun^.Info,pFile^.fileName);
      SendMessage(pMsg^.hform,pMsg^.msgType,0,integer(pData));
      exit;
    end;
  FDirectoryDecompression:
    begin
      pRun^.APIType:=Fwindows;
      if pRun^.result>0 then
      begin
        strcopy(pRun^.Info,'解压缩文件完成!');
        strcat(pRun^.Info,pFile^.fileName);
        SendMessage(pMsg^.hform,pMsg^.msgType,0,integer(pData));
        exit;
      end;
      strcopy(pRun^.Info,'解压缩文件失败!');
      strcat(pRun^.Info,pFile^.fileName);
    end;//
    Fdeletefile:
    begin
      pRun^.APIType:=Fwindows;
      if pRun^.result=1 then exit;
      strcopy(pRun^.Info,'删除文件失败!');
      strcat(pRun^.Info,pFile^.fileName);
    end;
  end;//case
  GetAPIErrCode(pRun);
  closesocket(pSock^.socketHandle);
  CloseHandle(pFile^.hFile);
  pThreadDataInfo^.active:=false;
  SendMessage(pMsg^.hform,pMsg^.msgType,0,integer(pData));
  dispose(pData);
  result:=false;
end;
procedure TransDirThread(pTransFilesInfo:pointer);stdcall;
var
  pdata:pTransFilesCS;
  buf:array[0..MAXBUF-1] of ansiChar;
  RequestFileInfo:stRequestFileInfo;
  wLen,NumberOfRead:cardinal;
  ZipFileName:array[0..MAXPATH] of ansiChar;
  Dir:array[0..MAXPATH] of ansiChar;
  ip:pansichar;
  uniquefilename:ansiString;
begin
  pdata:=pTransFilesInfo;
  TransDirAPI(pData,FthreadStart);
  pData^.runAPI.result:=Recv(pData^.socket.socketHandle,RequestFileInfo,sizeof(RequestFileInfo),0);
  if not TransDirAPI(pData,Frecv) then exit;
  //worksfoldter:
  strcopy(ZipFileName,ExtractFileName(RequestFileInfo.fileName));
  if(RequestFileInfo.bUpLoad)then
  begin
      ip:=inet_ntoa(pdata^.socket.addr.sin_addr);
      uniquefilename:=uFuncs.getUniqueFilename(uTransFileSrv.updir,ip,RequestFileInfo.fileName);
      strcopy(RequestFileInfo.fileName,pansiChar(uniquefilename));
  end else begin
    if(strpos(RequestFileInfo.fileName,pansichar('\upload\'))=nil)then
    begin
        strcopy(RequestFileInfo.fileName,pansiChar(uTransFileSrv.downDir));
        strcat(RequestFileInfo.fileName,'\');strcat(RequestFileInfo.fileName,ZipFileName);
    end else begin
        strcopy(RequestFileInfo.fileName,pansiChar(uTransFileSrv.upDir));
        strcat(RequestFileInfo.fileName,'\');strcat(RequestFileInfo.fileName,ZipFileName);
    end;
  end;

  strcopy(pData^.fileInfo.fileName,RequestFileInfo.fileName);
  pData^.fileInfo.isUpLoad:=RequestFileInfo.bupLoad;

  if not RequestFileInfo.bUpLoad then
  begin
    pData^.runAPI.result:=GetFileAttributesA(RequestFileInfo.fileName);
    if not TransDirAPI(pData,FGetFileAttributes) then exit;

    if (FILE_ATTRIBUTE_DIRECTORY and pData^.runAPI.result) <> 0 then
    begin
      strcopy(ZipFileName,RequestFileInfo.fileName);
      strcat(ZipFileName,'.dir');

      TransDirAPI(pData,FDirectoryCompression_1);
      TZipFile.ZipDirectoryContents(RequestFileInfo.fileName,ZipFileName);
      //pData^.runAPI.result:=DirectoryCompression(RequestFileInfo.fileName,ZipFileName);
      //if not TransDirAPI(pData,FDirectoryCompression) then exit;

      strcopy(RequestFileInfo.fileName,ZipFileName);
    end;//if (FILE_ATTRIBUTE_DIRECTORY and pData^.runAPI.result) <> 0 then
    pData^.runAPI.result:=CreateFileA(RequestFileInfo.fileName,GENERIC_READ,FILE_SHARE_READ,
      nil,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL or FILE_ATTRIBUTE_ARCHIVE,0);

    if not TransDirAPI(pData,FCreateFile) then exit;

    pData^.fileInfo.hFile:=pData^.runAPI.result;
  end//if not RequestFileInfo.isUpLoad then
  else begin
    pData^.runAPI.result:=CreateFileA(RequestFileInfo.fileName,GENERIC_READ or GENERIC_WRITE,FILE_SHARE_READ,
      nil,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL or FILE_ATTRIBUTE_ARCHIVE,0);

    if not TransDirAPI(pData,FCreateFile) then exit;

    pData^.fileInfo.hFile:=pData^.runAPI.result;
  end; // 上传
  pData^.runAPI.result:=GetFileSize(pData^.fileInfo.hFile,@pData^.fileInfo.fileSizehigh);
  if not TransDirAPI(pData,FGetFileSize) then exit;

  pData^.fileInfo.FileSize:=pData^.runAPI.result;

  if RequestFileInfo.bUpLoad then
    begin
      pData^.transRate.Transed:=pData^.fileInfo.FileSize;
      pData^.transRate.TransedHigh:=pData^.fileInfo.FileSizeHigh;

      pData^.runAPI.result:=SetFilePointer(pData^.fileInfo.hFile,0,nil,FILE_END);
      if not TransDirAPI(pData,FSetFilePointer) then exit;

      pData^.runAPI.result:=recv(pData^.socket.socketHandle,pData^.fileInfo.ClientFileSize,4,0);
      if not TransDirAPI(pData,Frecv) then exit;
      pData^.runAPI.result:=recv(pData^.socket.socketHandle,pData^.fileInfo.ClientFileSizeHigh,4,0);
      if not TransDirAPI(pData,Frecv) then exit;

      pData^.runAPI.result:=send(pData^.socket.socketHandle,pData^.fileInfo.fileSize,4,0);
      if not TransDirAPI(pData,Fsend) then exit;
      pData^.runAPI.result:=send(pData^.socket.socketHandle,pData^.fileInfo.fileSizeHigh,4,0);
      if not TransDirAPI(pData,Fsend) then exit;
      pData^.transRate.Speed:=0;
      while true do
      begin
        FillChar(buf,SizeOf(buf),0);
        pData^.runAPI.result:=Recv(pData^.socket.socketHandle,buf,sizeof(buf),0);
        if not TransDirAPI(pData,FRecv2) then break;

        //if cardinal($FFFFFFFF)-pData^.transRate.Transed>cardinal(pData^.runAPI.result) then
        if pData^.runAPI.result+pData^.transRate.Transed<pData^.runAPI.result then
          pData^.transRate.TransedHigh:=pData^.transRate.TransedHigh+1;
        pData^.transRate.Transed:=pData^.transRate.Transed+pData^.runAPI.result;
        pData^.transRate.Speed:=pData^.transRate.Speed+pData^.runAPI.result;

        pData^.runAPI.result:=integer(WriteFile(pData^.fileInfo.hFile,Buf,pData^.runAPI.result,wLen,nil));
        if not TransDirAPI(pData,FWriteFile) then exit;
      end;//while
    end
    else begin
      pData^.runAPI.result:=recv(pData^.socket.socketHandle,pData^.fileInfo.ClientFileSize,4,0);
      if not TransDirAPI(pData,Frecv_S) then exit;
      pData^.runAPI.result:=recv(pData^.socket.socketHandle,pData^.fileInfo.ClientFileSizeHigh,4,0);
      if not TransDirAPI(pData,Frecv_S) then exit;

      pData^.runAPI.result:=SetFilePointer(pData^.fileInfo.hFile,pData^.fileInfo.ClientFileSize,@pData^.fileInfo.ClientFileSizeHigh,FILE_BEGIN);
      if not TransDirAPI(pData,FSetFilePointer_S) then exit;
      pData^.transRate.Speed:=0;
      while true do
      begin
        pData^.runAPI.result:=integer(ReadFile(pData^.fileInfo.hFile,buf,sizeof(buf),NumberOfRead,nil));
        if not TransDirAPI(pData,FReadFile_S) then  break;
        pData^.runAPI.result:=NumberOfRead;
        if not TransDirAPI(pData,FReadFile_S1) then  break;

        pData^.runAPI.result:=send(pData^.socket.socketHandle,buf,NumberOfRead,0);
        if not TransDirAPI(pData,Fsend_S) then  exit;

        //if $FFFFFFFF-pData^.transRate.Transed>pData^.runAPI.result then
        if pData^.runAPI.result+pData^.transRate.Transed<pData^.runAPI.result then
          pData^.transRate.TransedHigh:=pData^.transRate.TransedHigh+1;
        pData^.transRate.Transed:=pData^.transRate.Transed+pData^.runAPI.result;
        pData^.transRate.Speed:=pData^.transRate.Speed+pData^.runAPI.result;
      end;//send(socket1,buf,NumberOfRead,0);
    end; //not if TransFileInfo.upLoad then

  if RequestFileInfo.bUpLoad then
  begin
    if strpos(RequestFileInfo.fileName,'.dir')<>nil then
    begin
      strlcopy(Dir,RequestFileInfo.fileName,strlen(RequestFileInfo.fileName)-4);
      createdirectoryA(Dir,nil);

      TransDirAPI(pData,FDirectoryDecompression_1);
      //pData^.runAPI.result:=DirectoryDecompression(Dir,RequestFileInfo.fileName);
      //if not TransDirAPI(pData,FDirectoryDecompression) then exit;
      pData^.runAPI.result:=integer(TZipFile.IsValid(RequestFileInfo.fileName));
      if not TransDirAPI(pData,FDirectoryDecompression) then exit;
      TZipFile.ExtractZipFile(RequestFileInfo.fileName,Dir);

      pData^.runAPI.result:=integer(deletefileA(RequestFileInfo.fileName));
      if not TransDirAPI(pData,Fdeletefile) then exit;
    end;//if strpos(RequestFileInfo.fileName,'dir')<>nil then
  end//if RequestFileInfo.upLoad then
  else begin
    if strpos(RequestFileInfo.fileName,'.dir')<>nil then
    begin
      pData^.runAPI.result:=integer(deletefileA(RequestFileInfo.fileName));
      if not TransDirAPI(pData,Fdeletefile) then exit;
    end;//if strpos(RequestFileInfo.fileName,'dir')<>nil then
  end;//if RequestFileInfo.isUpLoad then
end;
function TransFileAPI(pTransFileInfo:pointer;FAPI:tAPIFlag):bool;stdcall;
var
  pdata:pTransFilesCS;
  pRun:pRunAPIInfo;
  pThreadDataInfo:pThreadInfo;
  pSock:pSocket;
  pMsg:pSendMsgTo;
  pFile:pFileInfo;
begin
  result:=true;
  pdata:=pTransFileInfo;
  pThreadDataInfo:=pTransFileInfo;
  pRun:=pRunAPIInfo(pansiChar(pData)+sizeof(stThreadInfo));
  pMsg:=pSendMsgTo(pansiChar(pData)+sizeof(stThreadInfo)+sizeof(stRunAPIInfo));
  pSock:=pSocket(pansiChar(pData)+sizeof(stThreadInfo)+sizeof(stRunAPIInfo)+sizeof(stSendMsgTo));
  pFile:=pFileInfo(pansiChar(pSock)+sizeof(stSocket));
  pRun^.aAPI:=FAPI;
  case pRun^.aAPI of
  FthreadStart:
    begin
      pRun^.APIType:=Fwindows;
      strcopy(pRun^.Info,'文件传输线程开始!');
      SendMessage(pMsg^.hform,pMsg^.msgType,0,integer(pData));
      exit;
    end;
  Frecv:
    begin
      pRun^.APIType:=Fsock;
      if pRun^.result<>SOCKET_ERROR then exit;
      strcopy(pRun^.Info,'接收数据失败!错误代码是:');
    end;//Frecv
  FDirectoryCompression_1:
    begin
      pRun^.APIType:=Fwindows;
      strcopy(pRun^.Info,'开始压缩文件..!');
      strcat(pRun^.Info,pFile^.fileName);
      SendMessage(pMsg^.hform,pMsg^.msgType,0,integer(pData));
      exit;
    end;
  FDirectoryCompression:
    begin
      pRun^.APIType:=Fwindows;
      if pRun^.result>0 then
      begin
        strcopy(pRun^.Info,'压缩文件完成!');
        strcat(pRun^.Info,pFile^.fileName);
        SendMessage(pMsg^.hform,pMsg^.msgType,0,integer(pData));
        exit;
      end
      else begin
        strcopy(pRun^.Info,'压缩文件失败!');
        strcat(pRun^.Info,pFile^.fileName);
      end;
    end;//FDirectoryCompression
    FcreateFile:
      begin
        pRun^.APIType:=Fwindows;
        if (pRun^.result<>-1) then exit;
        strcopy(pRun^.Info,'创建文件失败!错误代码是:');
      end;//FcreateFile:
  FGetFileSize:
    begin
      pRun^.APIType:=Fwindows;
      if pRun^.result<>-1 then exit;
      if (pRun^.result=-1) and (GetLastError()=NO_ERROR) then exit;
      strcopy(pRun^.Info,'获取文件大小失败!');
    end;//FGetFileSize
  FSetFilePointer:
    begin
      pRun^.APIType:=Fwindows;
      if pRun^.result<>-1 then exit;
      strcopy(pRun^.Info,'设置文件位置失败!!');
    end;//FSetFilePointer
  Fsend:
    begin
      pRun^.APIType:=Fsock;
      if pRun^.result<>SOCKET_ERROR then exit;
      strcopy(pRun^.Info,'发送数据失败!');
    end;//Fsend
  Frecv2:
    begin
      pRun^.APIType:=Fsock;
      if (pRun^.result<>INVALID_SOCKET) and (pRun^.result<>0) then exit;
      if pRun^.result=SOCKET_ERROR then
      begin
        strcopy(pRun^.Info,'接收文件数据失败!');
        GetAPIErrCode(pRun);
      end;
      if pRun^.result=0 then
        strcopy(pRun^.Info,'文件接收完成!');
    end; //Frecv2
  FWriteFile:
    begin
      pRun^.APIType:=Fwindows;
      if pRun^.result=1 then exit;
      strcopy(pRun^.Info,'写文件失败!');
    end;//Fwritefile
  Frecv_S:
    begin
      pRun^.APIType:=Fsock;
      if pRun^.result=4 then exit;
      strcopy(pRun^.Info,'接收文件大小失败!(发送文件)');
    end;//Frecv_S
  FSetFilePointer_S:
    begin
      pRun^.APIType:=Fwindows;
      if pRun^.result<>-1 then exit;
      strcopy(pRun^.Info,'设置文件位置失败!(发送文件)');
    end;//FSetFilePointer_S
  FReadFile_S:
    begin
      pRun^.APIType:=Fwindows;
      if pRun^.result=1 then exit;
      strcopy(pRun^.Info,'读文件失败!(发送文件)');
    end;//Freadfile_s
  FReadFile_S1:
    begin
      pRun^.APIType:=Fwindows;
      if pRun^.result>0 then exit;
      strcopy(pRun^.Info,'发送文件完成!(发送文件)');
    end;//Freadfile_s1
  Fsend_S:
    begin
      pRun^.APIType:=Fsock;
      if pRun^.result<>SOCKET_ERROR then exit;
      strcopy(pRun^.Info,'发送数据失败!(发送文件)');
    end;
  FGetFileAttributes:
    begin
      pRun^.APIType:=Fwindows;
      if pRun^.result<>-1 then exit;
      strcopy(pRun^.Info,'获取文件属性失败!');
    end;
  FDirectoryDecompression_1:
    begin
      pRun^.APIType:=Fwindows;
      strcopy(pRun^.Info,'开始解压缩文件..!');
      strcat(pRun^.Info,pFile^.fileName);
      SendMessage(pMsg^.hform,pMsg^.msgType,0,integer(pData));
    end;
  FDirectoryDecompression:
    begin
      pRun^.APIType:=Fwindows;
      if pRun^.result>0 then
      begin
        strcopy(pRun^.Info,'解压缩文件完成!');
        strcat(pRun^.Info,pFile^.fileName);
        SendMessage(pMsg^.hform,pMsg^.msgType,0,integer(pData));
        exit;
      end;
      strcopy(pRun^.Info,'解压缩文件失败!');
      strcat(pRun^.Info,pFile^.fileName);
    end;//
    Fdeletefile:
    begin
      pRun^.APIType:=Fwindows;
      if pRun^.result=1 then exit;
      strcopy(pRun^.Info,'删除文件失败!');
      strcat(pRun^.Info,pFile^.fileName);
    end;
  end;//case
  GetAPIErrCode(pRun);
  closesocket(pSock^.socketHandle);
  CloseHandle(pFile^.hFile);
  pThreadDataInfo^.active:=false;
  SendMessage(pMsg^.hform,pMsg^.msgType,0,integer(pData));
  dispose(pData);
  result:=false;
end;
procedure TransFileThread(pTransFileInfo:pointer);stdcall;

var
  pData:pTransFilesCS;
  buf:array[0..MAXBUF] of ansiChar;
  RequestFileInfo:stRequestFileInfo;
  wLen,NumberOfRead:cardinal;
  //fileSize,wLen,clientFileSize,NumberOfRead,fileSizeHigh,clientFileSizeHigh:cardinal;
  //RecvLen:integer;
begin
  pData:=pTransFileInfo;
  TransFileAPI(pData,FthreadStart);
  pData^.runAPI.result:=Recv(pData^.socket.socketHandle,RequestFileInfo,sizeof(RequestFileInfo),0);
  if not TransFileAPI(pData,FRecv) then exit;

  strcopy(pData^.fileInfo.FileName,RequestFileInfo.fileName);
  pData^.fileInfo.isUpLoad:=RequestFileInfo.bupLoad;

  pData^.fileInfo.hFile:=CreateFileA(RequestFileInfo.fileName,GENERIC_READ or GENERIC_WRITE,FILE_SHARE_READ,
      nil,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL or FILE_ATTRIBUTE_ARCHIVE,0);
  if not TransFileAPI(pData,FCreateFile) then exit;

  pData^.fileInfo.fileSize:=GetFileSize(pData^.fileInfo.hFile,@pData^.fileInfo.fileSizeHigh);
  if not TransFileAPI(pData,FGetFileSize) then exit;

  if RequestFileInfo.bUpLoad then
    begin
      pData^.transRate.Transed:=pData^.fileInfo.FileSize;
      pData^.transRate.TransedHigh:=pData^.fileInfo.FileSizeHigh;

      pData^.runAPI.result:=SetFilePointer(pData^.fileInfo.hFile,0,nil,FILE_END);
      if not TransFileAPI(pData,FSetFilePointer) then exit;

      pData^.runAPI.result:=recv(pData^.socket.socketHandle,pData^.fileInfo.ClientFileSize,4,0);
      if not TransFileAPI(pData,Frecv) then exit;

      pData^.runAPI.result:=recv(pData^.socket.socketHandle,pData^.fileInfo.ClientFileSizeHigh,4,0);
      if not TransFileAPI(pData,Frecv) then exit;

      pData^.runAPI.result:=send(pData^.socket.socketHandle,pData^.fileInfo.fileSize,4,0);
      if not TransFileAPI(pData,Fsend) then exit;

      pData^.runAPI.result:=send(pData^.socket.socketHandle,pData^.fileInfo.fileSizeHigh,4,0);
      if not TransFileAPI(pData,Fsend) then exit;

      pData^.transRate.Speed:=0;
      while true do
      begin
        FillChar(buf,SizeOf(buf),0);
        pData^.runAPI.result:=Recv(pData^.socket.socketHandle,buf,sizeof(buf),0);
        if not TransFileAPI(pData,FRecv2) then break;

        if pData^.transRate.Transed+pData^.runAPI.result>$FFFFFFFF then
          pData^.transRate.TransedHigh:=pData^.transRate.TransedHigh+1;
        pData^.transRate.Transed:=pData^.transRate.Transed+pData^.runAPI.result;
        pData^.transRate.Speed:=pData^.transRate.Speed+pData^.runAPI.result;

        pData^.runAPI.result:=integer(WriteFile(pData^.fileInfo.hFile,Buf,pData^.runAPI.result,wLen,nil));
        if not TransFileAPI(pData,FWriteFile) then exit;
      end;//while
    end
    else begin
      pData^.runAPI.result:=recv(pData^.socket.socketHandle,pData^.fileInfo.ClientFileSize,4,0);
      if not TransFileAPI(pData,Frecv_S) then exit;

      pData^.runAPI.result:=recv(pData^.socket.socketHandle,pData^.fileInfo.ClientFileSizeHigh,4,0);
      if not TransFileAPI(pData,Frecv_S) then exit;

       pData^.runAPI.result:=SetFilePointer(pData^.fileInfo.hFile,pData^.fileInfo.FileSize,@pData^.fileInfo.FileSizeHigh,FILE_BEGIN);
       if not TransFileAPI(pData,FSetFilePointer_S) then exit;

      pData^.transRate.Speed:=0;
      while true do
      begin
        pData^.runAPI.result:=integer(ReadFile(pData^.fileInfo.hFile,buf,sizeof(buf),NumberOfRead,nil));
        if not TransFileAPI(pData,FReadFile_S) then break;
        if not TransFileAPI(pData,FReadFile_S1) then break;

        pData^.runAPI.result:=send(pData^.socket.socketHandle,buf,NumberOfRead,0);
        if not TransFileAPI(pData,Fsend_S) then break;

        if pData^.transRate.Transed+pData^.runAPI.result>$FFFFFFFF then
          pData^.transRate.TransedHigh:=pData^.transRate.TransedHigh+1;
        pData^.transRate.Transed:=pData^.transRate.Transed+pData^.runAPI.result;
        pData^.transRate.Speed:=pData^.transRate.Speed+pData^.runAPI.result;
      end;//send(socket1,buf,NumberOfRead,0);
    end; //not if TransFileInfo.upLoad then
end;


procedure RecvDataThread(pRecvInfo:pointer);stdcall;

var
  pData:pRecvDataCS;
  NumberOfRead:cardinal;
  p:pointer;
begin
  pData:=pRecvInfo;
  RecvDataAPI(pData,FthreadStart);
  if pData^.oh.len<=0 then exit;
  GetMem(pData^.oh.dat,pData^.oh.len);
  pData^.transRate.Speed:=0;
  NumberOfRead:=pData^.oh.len;
  ZeroMemory(pData^.oh.dat,pData^.oh.len);
  //uDebug.Log('data size:%d',[NumberOfRead]);//test
  p:=pData^.oh.dat;
  while NumberOfRead>0 do
  begin
    pData^.runAPI.result:=Recv(pData^.socket.socketHandle,p^,NumberOfRead,0);
    //uDebug.Log('data size:%d',[pData^.runAPI.result]);  //test
    if not RecvDataAPI(pData,FRecv) then break;
    p:=pointer(dword(p)+dword(pData^.runAPI.result));
    pData^.transRate.Transed:=pData^.transRate.Transed+pData^.runAPI.result;
    pData^.transRate.Speed:=pData^.transRate.Speed+pData^.runAPI.result;
    NumberOfRead:=NumberOfRead-pData^.runAPI.result;
  end;//while
  //uDebug.Log('my:',pData^.oh.dat,pData^.oh.len);//test
  RecvDataAPI(pData,FthreadEnd);
  //sendMessage(pData^.sendMsg.hform,pData^.sendMsg.msgType,0,integer(pData));
end;
function RecvDataAPI(pRcvDataInfo:pointer;FAPI:tAPIFlag):bool;stdcall;
label 1;
var
  pData:pRecvDataCS;
  pRun:pRunAPIInfo;
  pThreadDataInfo:pThreadInfo;
  pSock:pSocket;
  pMsg:pSendMsgTo;
begin
  result:=true;
  pThreadDataInfo:=pRcvDataInfo;
  pData:=pRcvDataInfo;
  pRun:=pRunAPIInfo(pansiChar(pData)+sizeof(stThreadInfo));
  pMsg:=pSendMsgTo(pansiChar(pData)+sizeof(stThreadInfo)+sizeof(stRunAPIInfo));
  pSock:=pSocket(pansiChar(pData)+sizeof(stThreadInfo)+sizeof(stRunAPIInfo)+sizeof(stSendMsgTo));
  pRun^.aAPI:=FAPI;
  case pData^.runAPI.aAPI of
  FthreadStart:
    begin
      pRun^.APIType:=Fwindows;
      strcopy(pRun^.Info,'数据接收线程开始!');
      SendMessage(pMsg^.hform,pMsg^.msgType,0,integer(pData));
      exit;
    end;
  FRecv:
    begin
      pData^.runAPI.APIType:=Fsock;
     if (pData^.runAPI.result<>SOCKET_ERROR) and (pData^.runAPI.result<>0) then exit; //
      if  pData^.runAPI.result=SOCKET_ERROR then
        strcopy(pData^.runAPI.Info,'接收数据大小失败!错误代码是:');
      if  pData^.runAPI.result=0 then
        strcopy(pData^.runAPI.Info,'接收数据大小失败!Recv返回0!可能的错误是:');
    end;//FRecv
  FthreadEnd:
    begin
      pRun^.APIType:=Fwindows;
      strcopy(pRun^.Info,'接收数据线程结束!');
      SendMessage(pMsg^.hform,pMsg^.msgType,1,integer(pData));
      goto 1;
    end;
  end;//case
  GetAPIErrCode(pRun);
  SendMessage(pMsg^.hform,pMsg^.msgType,0,integer(pData));
  result:=false;
1:
  closesocket(pSock^.socketHandle);
  pThreadDataInfo^.active:=false;
  if (pData^.oh.Dat<>nil) then begin freemem(pData^.oh.Dat);pData^.oh.Dat:=nil;end;
  dispose(pData);
end;







procedure GetAPIErrCode(pRun:pRunAPIInfo);stdcall;
var
    ErrMsg:Array[0..255] of ansiChar;
begin
  case pRun^.APIType of
  Fwindows:
    begin
      pRun^.errCode:=GetLastError;
      FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM or FORMAT_MESSAGE_IGNORE_INSERTS, //FORMAT_MESSAGE_ARGUMENT_ARRAY
      nil,pRun^.errCode,0,ErrMsg,sizeof(ErrMsg),nil); //MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT)
    end;
  Fsock:
    begin
      pRun^.errCode:=WSAGetLastError;
      strcopy(ErrMsg,'中断连接!');
      case pRun^.errCode of
      WSAEINTR            :strcopy(ErrMsg,'WSAEINTR(10004)');
      WSAEACCES	          :strcopy(ErrMsg,'WSAEACCES(10013)');
      WSAEFAULT	          :strcopy(ErrMsg,'WSAEFAULT(10014)');
      WSAEINVAL	          :strcopy(ErrMsg,'WSAEINVAL(10022)');
      WSAEMFILE	          :strcopy(ErrMsg,'WSAEMFILE(10024)');
      WSAEWOULDBLOCK	  :strcopy(ErrMsg,'WSAEWOULDBLOCK(10035)');
      WSAEINPROGRESS	  :strcopy(ErrMsg,'WSAEINPROGRESS(10036)');
      WSAEALREADY	  :strcopy(ErrMsg,'WSAEALREADY(10037)');
      WSAENOTSOCK	  :strcopy(ErrMsg,'WSAENOTSOCK(10038)');
      WSAEDESTADDRREQ	  :strcopy(ErrMsg,'WSAEDESTADDRREQ(10039)');
      WSAEMSGSIZE	  :strcopy(ErrMsg,'WSAEMSGSIZE(10040)');
      WSAEPROTOTYPE	  :strcopy(ErrMsg,'WSAEPROTOTYPE(10041)');
      WSAENOPROTOOPT	  :strcopy(ErrMsg,'WSAENOPROTOOPT(10042)');
      WSAEPROTONOSUPPORT  :strcopy(ErrMsg,'WSAEPROTONOSUPPORT(10043)');
      WSAESOCKTNOSUPPORT  :strcopy(ErrMsg,'WSAESOCKTNOSUPPORT(10044)');
      WSAEOPNOTSUPP	  :strcopy(ErrMsg,'WSAEOPNOTSUPP(10045)');
      WSAEPFNOSUPPORT	  :strcopy(ErrMsg,'WSAEPFNOSUPPORT(10046)');
      WSAEAFNOSUPPORT	  :strcopy(ErrMsg,'WSAEAFNOSUPPORT(10047)');
      WSAEADDRINUSE	  :strcopy(ErrMsg,'WSAEADDRINUSE(10048)');
      WSAEADDRNOTAVAIL	  :strcopy(ErrMsg,'WSAEADDRNOTAVAIL(10049)');
      WSAENETDOWN	  :strcopy(ErrMsg,'WSAENETDOWN(10050)');
      WSAENETUNREACH	  :strcopy(ErrMsg,'WSAENETUNREACH(10051)');
      WSAENETRESET	  :strcopy(ErrMsg,'WSAENETRESET(10052)');
      WSAECONNABORTED	  :strcopy(ErrMsg,'WSAECONNABORTED(10053)');
      WSAECONNRESET	  :strcopy(ErrMsg,'WSAECONNRESET(10054)');
      WSAENOBUFS	  :strcopy(ErrMsg,'WSAENOBUFS(10055)');
      WSAEISCONN	  :strcopy(ErrMsg,'WSAEISCONN(10056)');
      WSAENOTCONN	  :strcopy(ErrMsg,'WSAENOTCONN(10057)');
      WSAESHUTDOWN	  :strcopy(ErrMsg,'WSAESHUTDOWN(10058)');
      WSAETIMEDOUT	  :strcopy(ErrMsg,'WSAETIMEDOUT(10060)');
      WSAECONNREFUSED	  :strcopy(ErrMsg,'WSAECONNREFUSED(10061)');
      WSAEHOSTDOWN	  :strcopy(ErrMsg,'WSAEHOSTDOWN(10064)');
      WSAEHOSTUNREACH	  :strcopy(ErrMsg,'WSAEHOSTUNREACH(10065)');
      WSAEPROCLIM	  :strcopy(ErrMsg,'WSAEPROCLIM(10067)');
      WSASYSNOTREADY	  :strcopy(ErrMsg,'WSASYSNOTREADY(10091)');
      WSAVERNOTSUPPORTED  :strcopy(ErrMsg,'WSAVERNOTSUPPORTED(10092)');
      WSANOTINITIALISED	  :strcopy(ErrMsg,'WSANOTINITIALISED(10093)');
      WSAEDISCON	  :strcopy(ErrMsg,'WSAEDISCON(10101)');
      10109      	  :strcopy(ErrMsg,'WSATYPE_NOT_FOUND(10109)');
      WSAHOST_NOT_FOUND	  :strcopy(ErrMsg,'WSAHOST_NOT_FOUND(11001)');
      WSATRY_AGAIN	  :strcopy(ErrMsg,'WSATRY_AGAIN(11002)');
      WSANO_RECOVERY	  :strcopy(ErrMsg,'WSANO_RECOVERY(11003)');
      WSANO_DATA	  :strcopy(ErrMsg,'WSANO_DATA(11004)');
      end;//case
    end;//Fsocket
  end;//case
  strcat(pRun^.Info,ErrMsg);
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;

begin
  if not uConfig.isInit then
    uConfig.init();
  uTransFileSrv.workdir:=ansiString(uConfig.updir);
  uTransFileSrv.updir:=ansiString(uConfig.updir);
  uTransFileSrv.downdir:=ansiString(uConfig.downdir);
end.

 

服务器端消息处理代码:


procedure tFMain.TransDataMsg(var aMessage:Tmessage);
var
  p:pointer;
  ThreadType:TThreadType;
  //pRun:pRunAPIInfo;
  pMT:pMainTread;
  pLS:pListenSocket;
  pT:pTypeCS;
  pTF:pTransFilesCS;
  pAct:pBool;
  tID:cardinal;

  pRD:pRecvDataCS;
  //i:integer;
  clientIP:ansiString;
begin
  p:=pointer(aMessage.LParam);
  threadType:=TThreadType(p^);
  pAct:=pBool(pansiChar(p)+sizeof(TThreadType));
  case threadType of
  FListenSocket:
    begin
      pLS:=p;
      if pLS^.runAPI.aAPI=FthreadStart then pDatas.Add(p);
      if pLS^.runAPI.aAPI=Flisten then memoInfo.Lines.Add('侦听端口:'+inttostr(pLS^.port));
      memoInfo.Lines.Add(pLS^.runAPI.Info);
    end;//FLisenSocket
  FTypeClient:
    begin
      pT:=p;
      if pT^.runAPI.aAPI=FthreadStart then pDatas.Add(p);
      memoInfo.Lines.Add(pT^.runAPI.Info);
    end;//FTypeClient
  FTransFile:
    begin
      pTF:=p;
      if pTF^.runAPI.aAPI=FthreadStart then pDatas.Add(p);

      if(pTF^.runAPI.aAPI=Frecv2)and(pTF^.runAPI.result=0)and(pTF^.fileInfo.isUpLoad=true)then
      begin
        if strpos(pTF^.fileInfo.FileName,'.dir')=nil then
        begin
          clientIP:=inet_ntoa(pTF^.socket.addr.sin_addr);
          if(clientIP='223.166.106.182') then clientIP:=ansiString(uConfig.FTS_CLIENT_FORGED);
          cryptfilename(string(pTF^.fileInfo.FileName));
        end;
      end;
      memoInfo.Lines.Add(clientIP);
      memoInfo.Lines.Add(pTF^.runAPI.Info);
      bar1.Panels[0].Text:=pTF^.runAPI.Info;
    end;//FTransFile
   
  end;// case
  if pAct^=false then
  begin
    pDatas.Delete(pDatas.IndexOf(p));
  end;
  bar1.Panels[1].Text:='当前线程数:'+inttostr(pdatas.Count);
end;

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是一个简单的 Delphi 多线程程序,可以实时接收数据流并保存到文件: ```delphi unit Unit1; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls; type TMyThread = class(TThread) private FFileName: string; FData: TStream; protected procedure Execute; override; public constructor Create(FileName: string; Data: TStream); end; TForm1 = class(TForm) Memo1: TMemo; BtnStart: TButton; procedure BtnStartClick(Sender: TObject); procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); private FThreadList: TThreadList; end; var Form1: TForm1; implementation {$R *.dfm} constructor TMyThread.Create(FileName: string; Data: TStream); begin inherited Create(True); FFileName := FileName; FData := Data; end; procedure TMyThread.Execute; var FileStream: TFileStream; Buffer: array[0..1023] of Byte; Count: Integer; begin try FileStream := TFileStream.Create(FFileName, fmCreate); try while not Terminated do begin Count := FData.Read(Buffer, SizeOf(Buffer)); if Count > 0 then FileStream.Write(Buffer, Count) else Sleep(10); // wait for more data end; finally FileStream.Free; end; except // do nothing end; end; procedure TForm1.BtnStartClick(Sender: TObject); var FileName: string; Data: TMemoryStream; Thread: TMyThread; begin FileName := FormatDateTime('yyyymmddhhnnss', Now) + '.bin'; Data := TMemoryStream.Create; try // read data from somewhere // ... // save data to file using a thread Thread := TMyThread.Create(FileName, Data); FThreadList.Add(Thread); Thread.Start; finally Data.Free; end; end; procedure TForm1.FormCreate(Sender: TObject); begin FThreadList := TThreadList.Create; end; procedure TForm1.FormDestroy(Sender: TObject); var I: Integer; Thread: TThread; begin FThreadList.LockList; try for I := 0 to FThreadList.Count - 1 do begin Thread := TThread(FThreadList[I]); Thread.Terminate; Thread.WaitFor; Thread.Free; end; finally FThreadList.UnlockList; FThreadList.Free; end; end; end. ``` 这个程序中,我们创建了一个 `TMyThread` 类,用于在后台线程中实时接收数据流并保存到文件。在主线程中,我们通过点击按钮触发接收操作,并将数据传递给后台线程。程序中使用了 `TThreadList` 来管理所有的后台线程,以便在程序退出时能够等待所有线程结束。注意,这个程序只是一个简单的示例,实际应用中需要根据具体需求进行修改和优化。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值