最近用TServerSocket/TClientSocket做了一个简单的文件传输的东东,发现速度很慢,而且传大一点的文件就会像死机一样(用流的方式实现)。后来换成了TIdTCPServer/TIdTCPClient,用映射内存共享的方式实现了,速度也不慢,但文件的大小超出了内存的大小(物理内存+虚拟内存)就会报地址错误。这两种方式都有一个致命的问题一直都没有解决:当一个客户端和服务器正在传文件,如果有另一个客户端又连上服务器,则服务器会断掉与第一个客户端的连线。有没有哪位兄弟做过类似的东东,即:一个服务器可以同时向多个客户端传送文件。由于我是初级用户,一次只能最多给100分,如果不够,可以另起一个贴再给分。(软件的要求是:服务器24H挂在一台机器上,当有客户端连线上服务器,服务器作出回答,客户端3秒内收到回答后请求传送文件,开始从服务器传文件到客户端)

解决方案 »

  1.   

    楼上的,能不能把你用TIdTCPServer/TIdTCPClient开发的源码给贴出来啊
      

  2.   

    客户端(在窗体上放一个TOpenDialog,两个TButton,两个TEdit):
    unit uUpdate;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls, ComCtrls, IdBaseComponent, IdComponent,
      IdTCPConnection, IdTCPClient;const
    packsize=65000;//°ü´óСtype
    TRevBuffer=packed record
     masmID:Word;//δÓÃ
      ID:Word;//±ê¼Ç
      F1:DWord;
      F2:DWord;
      F3:DWord;
      F4:DWord;
      Len:DWord;
      MD:Int64;
    end;
    TSendBuffer=packed record
      masmID:Word;//δÓÃ
      ID:Word;//±ê¼Ç
      F1:DWord;
      F2:DWord;
      F3:DWord;
      F4:DWord;
      Len:DWord;//Êý¾ÝÇøµÄ´óС
      MD:Int64;//ÕªÒª
      buffer:Array[0..packsize-1] of byte;
    end;//ÐÔÄܼà²âÏß³Ì
    type
      TMonitorThread = class(TThread)
      private
        SecondTimer:DWord;
      protected
        procedure Execute; override;
      public
        constructor Create; reintroduce;
      end;type
      TForm1 = class;
      TSocketThread = class(TThread)
      private
        Rev:TRevBuffer;
        Snd:TSendBuffer;
        PRev,PSnd,TP,UP:PByte;
        TempPointer:PByte;
        RemainBytes:Word;
        ReceivedCounter:Integer;
        HeaderFinished,BodyFinished,PushTransporting:Boolean;    ThreadForm : TForm1;
        FClient:TIdTCPClient;
        SendBytes:DWord;//¸ÃÏß³ÌÒª´«ÊäµÄ×Ö½ÚÊý    FileMapPointer:PByte;//ÄÚ´æÓ³ÏñÎļþÖ¸Õë
    //    SendBlock:DWord;//¸ÃÏß³ÌÒª´«ÊäµÄ¿éÊý
        TransforCount,Transfor_T:DWord;
        procedure Process;
        procedure Branch;
        procedure RequestTransfer;
        procedure ServerReady;
        procedure Transporting;
      protected
        procedure Execute; override;
      public
        constructor Create(F: TForm1;Count:DWord;FileMap:PByte); reintroduce;
      end;
      
      TForm1 = class(TForm)
        OpenDialog1: TOpenDialog;
        Label1: TLabel;
        Label3: TLabel;
        Edit1: TEdit;
        Edit2: TEdit;
        btnChoice: TButton;
        Button1: TButton;
        procedure btnChoiceClick(Sender: TObject);
        procedure Button1Click(Sender: TObject);
      private
        { Private declarations }
      public
        FileSize:DWord;//Òª´«ÊäµÄÎļþ´óС
        Instructor:TProgressBar;
        MP:PByte;
        SocketThread:TSocketThread;
        Event:THandle;
        MonitorThread:TMonitorThread;
        { Public declarations }
      end;var
      Form1: TForm1;  var
      SentBytes:LongWord;
      
    implementation{$R *.dfm}constructor TSocketThread.Create(F: TForm1;Count:DWord;FileMap:PByte);
    begin
      inherited Create(false);
      ThreadForm := F;
      SendBytes:=Count;
      FileMapPointer:=FileMap;
      SentBytes:=0;
      ReceivedCounter:=32;
      PRev:=@Rev;
      PSnd:=@Snd;
      TempPointer:=PRev;
    end;procedure TForm1.btnChoiceClick(Sender: TObject);
    var
      F:Tsearchrec;
    begin
      IF OpenDialog1.Execute then
        Edit2.Text:=OpenDialog1.FileName;
      IF FindFirst(Edit2.Text,FaAnyfile,F)=0 then
        FileSize:=F.Size;
    end;procedure TForm1.Button1Click(Sender: TObject);
    var
      H,I,J,K,U:Integer;
      FH,MH:THandle;
    begin
    //½¨Á¢ÎļþÄÚ´æÓ³Ïñ
    //  Button1.Enabled:=False;
      FH:=FileOpen(Edit2.Text,fmOpenRead);
      MH:=CreateFileMapping(FH,nil,Page_ReadOnly,0,FileSize,nil);
      CloseHandle(FH);
      MP:=MapViewOfFile(MH,File_Map_Read,0,0,FileSize);
      CloseHandle(MH);
      If Instructor<>nil then
        Instructor.Free;
      Instructor:=TProgressBar.Create(self);
      Instructor.Left:=0;
      Instructor.Top:=Edit2.Top+Edit2.Height+15;
      Instructor.Width:=424;
      Instructor.Step:=1;
      Instructor.Parent:=Form1;  SocketThread:=TSocketThread.Create(self,FileSize,MP);
      Event:=CreateEvent(nil,False,False,nil);
    end;
      

  3.   

    procedure TSocketThread.Execute;
    var
      H,I,J:Integer;
      Thread_L:Integer;
      CurPointerOffset:DWord;
      FileName:String[255];
    begin
      FClient:=TIdTCPClient.Create(nil);
      FClient.Host:=ThreadForm.Edit1.Text;
      FClient.Port:=10888;
      try
        FClient.Connect(5000);
      except
        //&acute;í&Icirc;ó&acute;&brvbar;&Agrave;í
        Application.MessageBox('&Icirc;&THORN;·¨&Aacute;&not;&frac12;&Oacute;·&thorn;&Icirc;&ntilde;&AElig;÷','ERROR',MB_ICONERROR);
        FClient.Free;
        exit;
      end;
      //**&frac12;&Oacute;&Ecirc;&Otilde;·&thorn;&Icirc;&ntilde;&AElig;÷&ETH;&Aring;&Iuml;&cent;**//
      TransforCount:=(SendBytes-1) div packsize +1;//&ETH;è&Ograve;&ordf;&acute;&laquo;&Ecirc;&auml;TransforCount&cedil;&ouml;&Ecirc;&yacute;&frac34;&Yacute;&iquest;é
      Transfor_T:=SendBytes-(TransforCount-1)*packsize;//&Icirc;&sup2;°&Iacute;
      ThreadForm.Instructor.Max:=TransforCount;
      Snd.F2:=TransforCount;  Snd.ID:=0;//&Iacute;¨&Ouml;&ordf;·&thorn;&Icirc;&ntilde;&AElig;÷&frac12;¨&Aacute;&cent;&Icirc;&Auml;&frac14;&thorn;
      TP:=PSnd;
      Inc(TP,32);
      FileName:=ExtractFileName(ThreadForm.Edit2.Text);
      Snd.Len:=Length(FileName)+1;
      Snd.F1:=ThreadForm.FileSize;
      UP:=@FileName;
      move(UP^,TP^,Snd.Len);
      FClient.Socket.Send(PSnd^,Snd.Len+32);//&Iacute;¨&Ouml;&ordf;·&thorn;&Icirc;&ntilde;&AElig;÷
      
      repeat
        process;
      until
        Rev.ID=3;//Snd.F1=Snd.F2;
        
      SentBytes:=SentBytes+Snd.Len;//×&icirc;&ordm;ó&Ograve;&raquo;&cedil;&ouml;&Icirc;&sup2;°&Iacute;//    Form1.MonitorThread.Terminate;
        Snd.ID:=3;//&cedil;&aelig;&Ouml;&ordf;·&thorn;&Icirc;&ntilde;&AElig;÷&sup1;&Oslash;±&Otilde;&Auml;&Uacute;&acute;&aelig;&Oacute;°&Iuml;&ntilde;
        Snd.Len:=0;
        FClient.Socket.Send(PSnd^,32);
        UnMapViewOfFile(ThreadForm.MP);//&sup1;&Oslash;±&Otilde;&Auml;&Uacute;&acute;&aelig;&Oacute;&sup3;&Iuml;&ntilde;    CloseHandle(ThreadForm.Event);
    //    ThreadForm.Event;
        ThreadForm.Button1.Enabled:=True;  FClient.Disconnect;end;procedure TSocketThread.Process;
    var
      Bytes:Integer;
    begin
      IF RemainBytes>0 then//&Eacute;&Iuml;&acute;&Icirc;&raquo;&sup1;&Oacute;&ETH;×&Ouml;&frac12;&Uacute;&Atilde;&raquo;&Ecirc;&Otilde;&Egrave;&iexcl;  //&Oacute;&brvbar;&cedil;&Atilde;&sup3;&otilde;&Ecirc;&frac14;&raquo;&macr;
      begin
        ReceivedCounter:=ReceivedCounter-RemainBytes;
        IF ReceivedCounter>0 then//&frac12;&Oacute;&Ecirc;&Otilde;&Ecirc;&pound;&Oacute;à×&Ouml;&frac12;&Uacute;&ordm;ó&Ecirc;&yacute;&frac34;&Yacute;±¨&Eacute;&ETH;&Icirc;&acute;&Iacute;ê&sup3;&Eacute;&frac12;&Oacute;&Ecirc;&Otilde;
        begin
          Bytes:=RemainBytes;//&frac12;&Oacute;&Ecirc;&Otilde;&Ecirc;&pound;&Oacute;à
          RemainBytes:=0;
        end
        else
        begin
          IF ReceivedCounter=0 then//&Ecirc;&pound;&Oacute;à×&Ouml;&frac12;&Uacute;&cedil;&Otilde;&ordm;&Atilde;&frac12;&Oacute;&Ecirc;&Otilde;&Iacute;ê&sup3;&Eacute;
          begin
            Bytes:=RemainBytes;
            RemainBytes:=0;
            IF HeaderFinished then
              BodyFinished:=True
            else
            begin
              HeaderFinished:=True;//&Egrave;&ccedil;&sup1;&ucirc;&Iacute;·&Iacute;ê&sup3;&Eacute;&frac34;&Iacute;&Ecirc;&Ccedil;&Igrave;&aring;&Iacute;ê&sup3;&Eacute;&pound;&not;·&ntilde;&Ocirc;ò&Ouml;&raquo;&Ecirc;&Ccedil;&Iacute;·&Iacute;ê&sup3;&Eacute;
              PushTransporting:=True;
            end;
          end
          else
          begin   //&Ecirc;&pound;&Oacute;à×&Ouml;&frac12;&Uacute;&sup3;&not;&sup1;&yacute;±&frac34;&Ecirc;&yacute;&frac34;&Yacute;±¨&acute;ó&ETH;&iexcl;&pound;&not;&sup2;ú&Eacute;ú&Ecirc;&yacute;&frac34;&Yacute;&Otilde;&sup3;&Aacute;&not;
            Bytes:=ReceivedCounter+RemainBytes;
            RemainBytes:=RemainBytes-Bytes;//&Iacute;ê&sup3;&Eacute;±&frac34;&Ecirc;&yacute;&frac34;&Yacute;±¨&ordm;ó&Ecirc;&pound;&Oacute;à×&Ouml;&frac12;&Uacute;
            IF HeaderFinished then
              BodyFinished:=True
            else
            begin
              HeaderFinished:=True;//&Egrave;&ccedil;&sup1;&ucirc;&Iacute;·&Iacute;ê&sup3;&Eacute;&frac34;&Iacute;&Ecirc;&Ccedil;&Igrave;&aring;&Iacute;ê&sup3;&Eacute;&pound;&not;·&ntilde;&Ocirc;ò&Ouml;&raquo;&Ecirc;&Ccedil;&Iacute;·&Iacute;ê&sup3;&Eacute;
              PushTransporting:=True;
            end;
          end;
        end;
        FClient.ReadBuffer(TempPointer^,Bytes);
        Inc(TempPointer,Bytes);
        IF (Rev.Len=0) and HeaderFinished then//&Ouml;&raquo;&Ograve;&ordf;&Iacute;·
        begin
          HeaderFinished:=False;
          PushTransporting:=False;
          TempPointer:=PRev;
          ReceivedCounter:=32;//×&frac14;±&cedil;&Iuml;&Acirc;&Ograve;&raquo;&cedil;&ouml;&Iacute;·
          Branch;//·&Ouml;&Ouml;§&acute;&brvbar;&Agrave;í
        end
        else
        begin
          IF PushTransporting then //&Otilde;&yacute;&Ocirc;&Uacute;&acute;&laquo;&Ecirc;&auml;body
          begin
            PushTransporting:=False;
            ReceivedCounter:=Rev.Len;
          end
          else
          IF BodyFinished then
          begin
            TempPointer:=PRev;
            HeaderFinished:=False;
            BodyFinished:=False;
            ReceivedCounter:=32;//×&frac14;±&cedil;&Iuml;&Acirc;&Ograve;&raquo;&cedil;&ouml;&Iacute;·
            Branch;//·&Ouml;&Ouml;§&acute;&brvbar;&Agrave;í
          end
        end;
      end
      else
      begin//RemainBytes=0
        Try
          RemainBytes:=FClient.ReadFromStack(True,15000,True);
        Except
          exit;
        end;
      end;
    end;procedure TSocketThread.Branch;
    begin
      case Rev.ID of
      1:ServerReady;
      2:transporting;
      end;
    end;procedure TSocketThread.ServerReady;
    begin
      RequestTransfer;
      Form1.MonitorThread:=TMonitorThread.Create;
    end;procedure TSocketThread.RequestTransfer;
    begin
      Snd.ID:=1;
      Snd.F1:=0;
      Snd.Len:=0;
      FClient.Socket.Send(PSnd^,32);
    end;procedure TSocketThread.transporting;
    var
      FTT,FUU:PByte;
    begin
      SentBytes:=SentBytes+Snd.Len;//&Ograve;&Ntilde;·&cent;&Euml;&Iacute;×&Ouml;&frac12;&Uacute;
      Snd.ID:=2;
      Snd.F1:=Rev.F1;
      IF Snd.F1=Snd.F2 then
        Snd.Len:=Transfor_T
      else
        Snd.Len:=packsize;
      Snd.F3:=(Snd.F1-1)*packsize;
      FTT:=FileMapPointer;
      INC(FTT,(Snd.F1-1)*packsize);
      FUU:=PSnd;
      Inc(FUU,32);
      move(FTT^,FUU^,Snd.Len);
      FClient.Socket.Send(PSnd^,Snd.Len+32);
      ThreadForm.Instructor.StepIt;
    end;constructor TMonitorThread.Create;
    begin
      inherited Create(false);
      SecondTimer:=0;
    end;
    procedure TMonitorThread.Execute;
    var
      H,I,V:DWord;
    begin
    {  While Not(Terminated) do
      begin
        Sleep(1000);
        SecondTimer:=SecondTimer+1;
        H:=0;
        For I:=0 to ThreadCount-1 do
        H:=H+SentBytes[I];
        V:=H div SecondTimer;
        V:=V div 1024;
        Form1.StatusBar1.Panels[2].Text:='&AElig;&frac12;&frac34;ù&Euml;&Ugrave;&Acirc;&Ecirc;:'+Inttostr(V)+'KB/S';
      end; }
    end;end.
      

  4.   

    客户端(在窗体上放一个TOpenDialog,两个TButton,两个TEdit):
    unit uUpdate;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls, ComCtrls, IdBaseComponent, IdComponent,
      IdTCPConnection, IdTCPClient;const
    packsize=65000;//包大小type
    TRevBuffer=packed record
     masmID:Word;//未用
      ID:Word;//标记
      F1:DWord;
      F2:DWord;
      F3:DWord;
      F4:DWord;
      Len:DWord;
      MD:Int64;
    end;
    TSendBuffer=packed record
      masmID:Word;//未用
      ID:Word;//标记
      F1:DWord;
      F2:DWord;
      F3:DWord;
      F4:DWord;
      Len:DWord;//数据区大小
      MD:Int64;//摘要
      buffer:Array[0..packsize-1] of byte;
    end;//性能监测线程
    type
      TMonitorThread = class(TThread)
      private
        SecondTimer:DWord;
      protected
        procedure Execute; override;
      public
        constructor Create; reintroduce;
      end;type
      TForm1 = class;
      TSocketThread = class(TThread)
      private
        Rev:TRevBuffer;
        Snd:TSendBuffer;
        PRev,PSnd,TP,UP:PByte;
        TempPointer:PByte;
        RemainBytes:Word;
        ReceivedCounter:Integer;
        HeaderFinished,BodyFinished,PushTransporting:Boolean;    ThreadForm : TForm1;
        FClient:TIdTCPClient;
        SendBytes:DWord;//改线程要传输的字节数
        FileMapPointer:PByte;//内存映象文件指针
        TransforCount,Transfor_T:DWord;
        procedure Process;
        procedure Branch;
        procedure RequestTransfer;
        procedure ServerReady;
        procedure Transporting;
      protected
        procedure Execute; override;
      public
        constructor Create(F: TForm1;Count:DWord;FileMap:PByte); reintroduce;
      end;  
      TForm1 = class(TForm)
        OpenDialog1: TOpenDialog;
        Label1: TLabel;
        Label3: TLabel;
        Edit1: TEdit;
        Edit2: TEdit;
        btnChoice: TButton;
        Button1: TButton;
        procedure btnChoiceClick(Sender: TObject);
        procedure Button1Click(Sender: TObject);
      private
        { Private declarations }
      public
        FileSize:DWord;//要传输的文件大小
        Instructor:TProgressBar;
        MP:PByte;
        SocketThread:TSocketThread;
        Event:THandle;
        MonitorThread:TMonitorThread;
        { Public declarations }
      end;var
      Form1: TForm1;  var
      SentBytes:LongWord;
      
    implementation{$R *.dfm}constructor TSocketThread.Create(F: TForm1;Count:DWord;FileMap:PByte);
    begin
      inherited Create(false);
      ThreadForm := F;
      SendBytes:=Count;
      FileMapPointer:=FileMap;
      SentBytes:=0;
      ReceivedCounter:=32;
      PRev:=@Rev;
      PSnd:=@Snd;
      TempPointer:=PRev;
    end;procedure TForm1.btnChoiceClick(Sender: TObject);
    var
      F:Tsearchrec;
    begin
      IF OpenDialog1.Execute then
        Edit2.Text:=OpenDialog1.FileName;
      IF FindFirst(Edit2.Text,FaAnyfile,F)=0 then
        FileSize:=F.Size;
    end;procedure TForm1.Button1Click(Sender: TObject);
    var
      H,I,J,K,U:Integer;
      FH,MH:THandle;
    begin
    //建立文件内存映象
    //  Button1.Enabled:=False;
      FH:=FileOpen(Edit2.Text,fmOpenRead);
      MH:=CreateFileMapping(FH,nil,Page_ReadOnly,0,FileSize,nil);
      CloseHandle(FH);
      MP:=MapViewOfFile(MH,File_Map_Read,0,0,FileSize);
      CloseHandle(MH);
      If Instructor<>nil then
        Instructor.Free;
      Instructor:=TProgressBar.Create(self);
      Instructor.Left:=0;
      Instructor.Top:=Edit2.Top+Edit2.Height+15;
      Instructor.Width:=424;
      Instructor.Step:=1;
      Instructor.Parent:=Form1;  SocketThread:=TSocketThread.Create(self,FileSize,MP);
      Event:=CreateEvent(nil,False,False,nil);
    end;procedure TSocketThread.Execute;
    var
      H,I,J:Integer;
      Thread_L:Integer;
      CurPointerOffset:DWord;
      FileName:String[255];
    begin
      FClient:=TIdTCPClient.Create(nil);
      FClient.Host:=ThreadForm.Edit1.Text;
      FClient.Port:=10888;
      try
        FClient.Connect(5000);
      except
        //错误处理
        Application.MessageBox('无法连接服务器','ERROR',MB_ICONERROR);
        FClient.Free;
        exit;
      end;
      //**接收服务器信息**//
      TransforCount:=(SendBytes-1) div packsize +1;//需要传输TransforCount个数据块
      Transfor_T:=SendBytes-(TransforCount-1)*packsize;//尾巴
      ThreadForm.Instructor.Max:=TransforCount;
      Snd.F2:=TransforCount;  Snd.ID:=0;//通知服务器建立文件
      TP:=PSnd;
      Inc(TP,32);
      FileName:=ExtractFileName(ThreadForm.Edit2.Text);
      Snd.Len:=Length(FileName)+1;
      Snd.F1:=ThreadForm.FileSize;
      UP:=@FileName;
      move(UP^,TP^,Snd.Len);
      FClient.Socket.Send(PSnd^,Snd.Len+32);//通知服务器
      
      repeat
        process;
      until
        Rev.ID=3;
        
      SentBytes:=SentBytes+Snd.Len;//最后一个尾巴//    Form1.MonitorThread.Terminate;
        Snd.ID:=3;//告知服务器关闭内存映象
        Snd.Len:=0;
        FClient.Socket.Send(PSnd^,32);
        UnMapViewOfFile(ThreadForm.MP);//关闭内存映象
        CloseHandle(ThreadForm.Event);
    //    ThreadForm.Event;
        ThreadForm.Button1.Enabled:=True;  FClient.Disconnect;end;
      

  5.   

    procedure TSocketThread.Process;
    var
      Bytes:Integer;
    begin
      IF RemainBytes>0 then//上次还有字节未收取
      begin
        ReceivedCounter:=ReceivedCounter-RemainBytes;
        IF ReceivedCounter>0 then//接收剩余字节后数据报尚未完成接收
        begin
          Bytes:=RemainBytes;//接收剩余
          RemainBytes:=0;
        end
        else
        begin
          IF ReceivedCounter=0 then//剩余字节刚好接收完成
          begin
            Bytes:=RemainBytes;
            RemainBytes:=0;
            IF HeaderFinished then
              BodyFinished:=True
            else
            begin
              HeaderFinished:=True;// 如果头完成,则是体完成,否则则是头完成
              PushTransporting:=True;
            end;
          end
          else
          begin   //剩余字节超过本数据报大小,产生数据粘连
            Bytes:=ReceivedCounter+RemainBytes;
            RemainBytes:=RemainBytes-Bytes;//完成本数据报后剩余字节数
            IF HeaderFinished then
              BodyFinished:=True
            else
            begin
              HeaderFinished:=True;// 如果头完成,则是体完成,否则则是头完成
              PushTransporting:=True;
            end;
          end;
        end;
        FClient.ReadBuffer(TempPointer^,Bytes);
        Inc(TempPointer,Bytes);
        IF (Rev.Len=0) and HeaderFinished then//只要头
        begin
          HeaderFinished:=False;
          PushTransporting:=False;
          TempPointer:=PRev;
          ReceivedCounter:=32;//准备下一个头
          Branch;//分支处理
        end
        else
        begin
          IF PushTransporting then //正在传输Body
          begin
            PushTransporting:=False;
            ReceivedCounter:=Rev.Len;
          end
          else
          IF BodyFinished then
          begin
            TempPointer:=PRev;
            HeaderFinished:=False;
            BodyFinished:=False;
            ReceivedCounter:=32;//准备下一个头
            Branch;//分支处理
          end
        end;
      end
      else
      begin//RemainBytes=0
        Try
          RemainBytes:=FClient.ReadFromStack(True,15000,True);
        Except
          exit;
        end;
      end;
    end;procedure TSocketThread.Branch;
    begin
      case Rev.ID of
      1:ServerReady;
      2:transporting;
      end;
    end;procedure TSocketThread.ServerReady;
    begin
      RequestTransfer;
      Form1.MonitorThread:=TMonitorThread.Create;
    end;procedure TSocketThread.RequestTransfer;
    begin
      Snd.ID:=1;
      Snd.F1:=0;
      Snd.Len:=0;
      FClient.Socket.Send(PSnd^,32);
    end;procedure TSocketThread.transporting;
    var
      FTT,FUU:PByte;
    begin
      SentBytes:=SentBytes+Snd.Len;//已发送字节
      Snd.ID:=2;
      Snd.F1:=Rev.F1;
      IF Snd.F1=Snd.F2 then
        Snd.Len:=Transfor_T
      else
        Snd.Len:=packsize;
      Snd.F3:=(Snd.F1-1)*packsize;
      FTT:=FileMapPointer;
      INC(FTT,(Snd.F1-1)*packsize);
      FUU:=PSnd;
      Inc(FUU,32);
      move(FTT^,FUU^,Snd.Len);
      FClient.Socket.Send(PSnd^,Snd.Len+32);
      ThreadForm.Instructor.StepIt;
    end;constructor TMonitorThread.Create;
    begin
      inherited Create(false);
      SecondTimer:=0;
    end;procedure TMonitorThread.Execute;
    var
      H,I,V:DWord;
    begin
    {  While Not(Terminated) do
      begin
        Sleep(1000);
        SecondTimer:=SecondTimer+1;
        H:=0;
        For I:=0 to ThreadCount-1 do
        H:=H+SentBytes[I];
        V:=H div SecondTimer;
        V:=V div 1024;
        Form1.StatusBar1.Panels[2].Text:='&AElig;&frac12;&frac34;ù&Euml;&Ugrave;&Acirc;&Ecirc;:'+Inttostr(V)+'KB/S';
      end; }
    end;end.
      

  6.   

    服务器端(一个TIdTCPServer,TMemo,两个TButton):
    unit uUpdate;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls, IdBaseComponent, IdComponent, IdTCPServer, ComCtrls;const packsize=65000;
    var
      FileMapPointer:PByte;
      FileSize:LongWord;
      FN:String[250];type TSend=packed record
         masmID:Word;
         ID:Word;
         F1:DWord;
         F2:DWord;
         F3:DWord;
         F4:DWord;
         Len:DWord;
         MD:Int64;
    end;
    type TReceive=packed record
         masmID:Word;
         ID:Word;
         F1:DWord;
         F2:DWord;
         F3:DWord;
         F4:DWord;
         Len:DWord;
         MD:Int64;
         Buffer:Array[0..packsize-1] of byte;
    end;type
      TForm1 = class;
      TSocketProcesser=Class
      private
        AOne:TidPeerThread;
        HeaderFinished,BodyFinished,PushTransporting:Boolean;
        RemainBytes:Word;
        ReceivedCounter:Integer;//要接收的字节数
        Rev:TReceive;
        Snd:TSend;
        PRev,PSnd:PByte;
        TempPointer:PByte;
        procedure Branch;//处理
        procedure Echo(Option:Word);
        procedure BuildFile;//建立文件内存映象
        procedure Pass;//通知客户端可以传输
        procedure FileTransport;
      public
        frm:TForm1;
        constructor Create(AThread:TidPeerThread;F:TForm1);reintroduce;
        procedure Process;
      end;
      
      TForm1 = class(TForm)
        Memo1: TMemo;
        IdTCPServer1: TIdTCPServer;
        Button1: TButton;
        Button2: TButton;
        procedure IdTCPServer1Connect(AThread: TIdPeerThread);
        procedure IdTCPServer1Disconnect(AThread: TIdPeerThread);
        procedure IdTCPServer1Execute(AThread: TIdPeerThread);
        procedure Button1Click(Sender: TObject);
        procedure FormClose(Sender: TObject; var Action: TCloseAction);
        procedure Button2Click(Sender: TObject);
        procedure FormCreate(Sender: TObject);
      private
        { Private declarations }
      public
        Instructor:TProgressBar;
        { Public declarations }
      end;var
      Form1: TForm1;implementation{$R *.dfm}procedure TForm1.IdTCPServer1Connect(AThread: TIdPeerThread);
    var
      DoP:TSocketProcesser;
    begin
      DoP:=TSocketProcesser.Create(AThread,self);
      Athread.Data:=Dop;
    end;procedure TForm1.IdTCPServer1Disconnect(AThread: TIdPeerThread);
    begin
      TSocketProcesser(AThread.Data).Free;
      AThread.Data:=Nil;
    end;procedure TForm1.IdTCPServer1Execute(AThread: TIdPeerThread);
    begin
      TSocketProcesser(AThread.Data).Process;
    end;procedure TForm1.Button1Click(Sender: TObject);
    begin
      IF IdTCPServer1.Active then
      begin
        IdTCPServer1.Active:=False;
        Button1.Caption:='启动服务';
      end
      else
      begin
        IdTCPServer1.Active:=True;
        Button1.Caption:='终止服务';
      end;
    end;procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
    begin
      IdTCPServer1.Active:=False;
    end;procedure TForm1.Button2Click(Sender: TObject);
    begin
      Memo1.Lines.Clear;
    end;procedure TSocketProcesser.Branch;
    begin
      case Rev.ID of
        0: BuildFile;
        1: Pass;
        2: FileTransport;
        3:
        begin
          UnMapViewOfFile(FileMapPointer);//关闭文件
          Form1.Memo1.Lines.Add(FN+','+TimeToStr(now())+'结束传输');
        end;
      end;
    end;procedure TSocketProcesser.BuildFile;
    var
      FileName:String[250];
      PS,PD:PByte;
      FH1,FH2:THandle;
      size:DWord;
      str:string;
    begin
      PS:=TempPointer;
      Inc(PS,32);
      PD:=@FileName;
      move(PS^,PD^,Rev.Len);
      FN:=FileName;
      size:=Rev.F1;//得到文件长度
      str:=ExtractFilePath(Application.ExeName);
      if not DirectoryExists(str + 'Files\') then
        CreateDir(str + 'Files\');
      FH1:=FileCreate(str+'files\'+FileName);
      
      FileClose(FH1);
      FH1:=FileOpen(str+'files\'+FileName,fmOpenreadWrite);
      FH2:=CreateFileMapping(FH1,nil,Page_ReadWrite,0,size,nil);
      CloseHandle(FH1);
      FileMapPointer:=MapViewOfFile(FH2,File_Map_All_Access,0,0,size);
      FileSize:=size;//
      CloseHandle(FH2);
      Form1.Memo1.Lines.Add(FileName+'长度'+inttostr(FileSize)+','+TimetoStr(Now())+'开始传输');
      Echo(1);
    end;
      

  7.   

    procedure TSocketProcesser.Pass;//索取数据报
    begin
      Snd.F1:=Rev.F1+1;//下一个数据报
      Snd.F2:=Rev.F2;
      Echo(2);
    end;procedure TSocketProcesser.FileTransport;
    var
      TempFileMapPointer,PB:PByte;
    begin
      TempFileMapPointer:=FileMapPointer;
      PB:=PRev;
      Inc(TempFileMapPointer,Rev.F3);
      Inc(PB,32);
      move(PB^,TempFileMapPointer^,Rev.Len);
      IF Rev.F1<Rev.F2 then//请求下一个数据报
        Pass
      else//如果相等,则接收完毕
        Echo(3);
    end;constructor TSocketProcesser.Create(AThread:TidPeerThread;F:TForm1);
    begin
      inherited Create;
      frm:=F;
      AOne:=AThread;
      ReceivedCounter:=32;//首先接收32字节
      HeaderFinished:=False;
      BodyFinished:=False;
      PushTransporting:=False;
      RemainBytes:=0;
      PRev:=@Rev;
      PSnd:=@Snd;
      TempPointer:=PRev;
    end;procedure TSocketProcesser.Process;
    var
      Bytes:Integer;
    begin
      IF ReceivedCounter=0 then
        exit;
      IF RemainBytes>0 then//上次还有字节未收取
      begin
        ReceivedCounter:=ReceivedCounter-RemainBytes;
        IF ReceivedCounter>0 then//接收剩余字节后数据报尚未完成接收
        begin
          Bytes:=RemainBytes;//接收剩余
          RemainBytes:=0;
        end
        else
        begin
          IF ReceivedCounter=0 then//剩余字节刚好接收完成
          begin
            Bytes:=RemainBytes;
            RemainBytes:=0;
            IF HeaderFinished then
              BodyFinished:=True
            else
            begin
              HeaderFinished:=True;//如果头完成则是体完成,否则只是头完成
              PushTransporting:=True;
            end;
          end
          else
          begin   //剩余字节超过本数据报大小,产生数据粘连
            Bytes:=ReceivedCounter+RemainBytes;
            RemainBytes:=RemainBytes-Bytes;//完成本数据报后剩余字节
            IF HeaderFinished then
              BodyFinished:=True
            else
            begin
              HeaderFinished:=True;//如果头完成则体完成,否则只是头
    PushTransporting:=True;
            end;
          end;
        end;
        AOne.Connection.ReadBuffer(TempPointer^,Bytes);
        Inc(TempPointer,Bytes);
        frm.Instructor.StepIt;
        IF (Rev.Len=0) and HeaderFinished then//只要头
        begin
          HeaderFinished:=False;
          PushTransporting:=False;
          TempPointer:=PRev;
          ReceivedCounter:=32;//准备下一个头
          Branch;//分支处理
        end
        else
        begin
          IF PushTransporting then //正在传输body
          begin
            PushTransporting:=False;
            ReceivedCounter:=Rev.Len;
          end
          else
          IF BodyFinished then
          begin
            TempPointer:=PRev;
            HeaderFinished:=False;
            BodyFinished:=False;
            ReceivedCounter:=32;//准备下一个头
            Branch;//分支处理
          end
        end;
      end
      else
      begin
        Try
          RemainBytes:=AOne.Connection.ReadFromStack(True,15000,True); {//返回本次要传输的字节大小(不是文件大小)}
        Except
          exit;
        end;
      end;
    end;procedure TSocketProcesser.Echo(Option: Word);
    begin
      Snd.ID:=Option;
      Snd.Len:=0;
      AOne.Connection.Socket.Send(PSnd^,32);
    end;procedure TForm1.FormCreate(Sender: TObject);
    begin
      If Instructor<>nil then
        Instructor.Free;
      Instructor:=TProgressBar.Create(self);
      Instructor.Left:=8;
      Instructor.Top:=Memo1.Top+Memo1.Height+10;
      Instructor.Width:=400;
      Instructor.Step:=1;
      Instructor.Parent:=Form1;
    end;end.
      

  8.   

    to:tanweibiao2000(延平) 问题解决了吗,我正要做这个,能不能把代码发给我,谢谢
    [email protected]
      

  9.   

    是啊,能不能给我一份,我也在做这个,先谢谢!
    [email protected]
      

  10.   


    我没做过ftp这方面的东东,
    你有没有代码,如果有能不能给我一份
    [email protected]
      

  11.   

    Delphi自带的Demo在Indy目录下有个简单的ftp服务器和客户端程序,你先看看那个吧。
      

  12.   

    我没有看代码,但是听到“文件的大小超出了内存的大小(物理内存+虚拟内存)就会报地址错误”,觉得可以用blockread、blockwrite来分段传输啊