怎样在局域网内传输exe文件?郁闷了,这方面资料我都找不到哦,兄弟们帮忙哦
我的qq25549894  邮箱[email protected]

解决方案 »

  1.   


    www.2ccc.com或www.delphifans.com上找源码,肯定有,我见过~
      

  2.   


    socket 编程么?下面这个是我自己写得 demo 希望能帮到你哦。---------------------------------
    【原创】『局域网内』 TCP传文件的demo源码分析--server端最近在写一个 聊天室程序,因为其中用到点对点传文件
    这个应该是比较典型的文件传输程序,相信会对一些传输文件的朋友有帮助。
    所以便贴了出来,其中对于文件流的传输处理比较有意义的
    这个demo是 客户端(client)----->服务端(server) 采用的是TCP协议,实现多播稳定传输大文件。原来我以为是 UDP协议的呢
    一看 原来是 TCP的 赫赫 不管他 分析一下 其中对文件流的操作部分值得借鉴下面 我将我对代码的理解 主要是比较难明白的部分做一下旁注,也算是学习笔记,贴出来希望能对新手有帮助,对高手呢 也有启发作用  :)双斜杠以后是我的注释
    --------------------------------------总的思路,就是客户端朝服务端发送数据流,然后按照顺序一个一个发过来的,然后,服务端也是一个一个接受,按顺序一个一个读,直到读完为止。
    ---------------------------------------
      

  3.   

    //先看 server端的代码unit uServer;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, ComCtrls, ExtDlgs, IdBaseComponent, IdComponent, IdTCPServer;type  TDataState = (dstNone, dstReceiving);    
    //定义一个枚举类型TDataState,其中只有两个值dstNone和dstReceiving
      //定义TThreadData类型,其对象用来保存一个连接的状态以及一些变量
    //以下的定义其实相当于自己定义了一个控件 TThreadData ,里面有自己的方法和属性TThreadData = class
        private  //--------------------私有方法属性
        
        FState: TDataState;  //--------------属性FState,类型为前面定义的枚举型
          FFileSize: Integer;    //--------------属性FFileSize,整型
          FStream: TFileStream;  //------------属性FStream,TFileStream类型      procedure SetState(const Value: TDataState); // ---------方法SetState
          procedure SetFileSize(const Value: Integer);    // ---------方法SetFileSize
          procedure SetStream(const Value: TFileStream);// --------方法SetStream
        
    public    //公有方法属性
        constructor Create;  //---------------构造方法,主要是用于该类型的对象生成
        destructor Destroy; override;  //-----------析构方法,主要用于该类型的对象的注销    property State : TDataState read FState write SetState;  //-------属性State定义
        property FileSize : Integer read FFileSize write SetFileSize; //------属性FileSize 定义
        property Stream : TFileStream read FStream write SetStream;//-----属性stream定义
      end;//接下来就是 主窗口的组件创建和定义了type
      TfmServer = class(TForm)    //定义了一个窗口 类TfmServer 
        ProgressBar1: TProgressBar;    //在里面放进进度显示条ProgressBar1:
        IdTCPServer1: TIdTCPServer;    //放一个IdTCPServer控件 IdTCPServer1  //下面两个是 indy控件IdTCPServer的两个方法,一个是建立连接时用,一个是接受传输时用 
        procedure IdTCPServer1Connect(AThread: TIdPeerThread);
        procedure IdTCPServer1Execute(AThread: TIdPeerThread);
      private
        { Private declarations }
      public
        { Public declarations }
      end;var
      fmServer: TfmServer;  //窗口建立implementation{$R *.dfm}procedure TfmServer.IdTCPServer1Connect(AThread: TIdPeerThread);
    begin  AThread.Data := TThreadData.Create;  //看到了吧,AThread.Data 就是利用TThreadData里的构造方法创建的对象
      with AThread.Data as TThreadData do
      begin
        State := dstNone;
      end;//上面这段是用来设置对象AThread.Data里的属性State的值为 dstNone ,这个属性表示目前有没有正在接受文件传输,刚开启服务监听,连接是没有的,所以赋值dstNone 
    end;
    //下面这个事件Execute是表示 有数据传过来的时候的执行内容,是IdTCPServer的一个方法procedure TfmServer.IdTCPServer1Execute(AThread: TIdPeerThread);var  //下面定义一些局部变量
      aFileSize : Integer;      //aFileSize用来表示文件大小,整型
      aFileName : String;    //aFileName表示文件名,字串型
      Buff : array[0..1023] of Byte;  // Buff 缓存区大小设置,byte型
      ReadCount : Integer;  //实际每次读取文件块的大小,整型
    begin          with AThread.Data as TThreadData do    //针对对AThread.Data对象 进行操作(程序块)
              begin
                    if State = dstNone then        //如果AThread.Data状态属性为dstNone ,即没人连接时
                        begin
                            if not AThread.Terminated and AThread.Connection.Connected then  //如果有连接时
                                  begin
                                                      //读取文件名
                      aFileName := AThread.Connection.ReadLn(#13#10, 100);
                                      
                                        //如果读到文件名为空就退出
                                        if aFileName = '' then
                                        Exit;                    
              AThread.Connection.WriteLn;//---返回确认文件传输标志,和前面的Readln相互对应
                      AThread.Connection.ReadBuffer(aFileSize, 4);----//开始读取文件长度,放进变量aFileSize中
                      FileSize := aFileSize;
                      ProgressBar1.Max := FileSize;
                      Stream := TFileStream.Create(aFileName, fmCreate);//创建一个文件流
                      State := dstReceiving;
              end      end;  //以下是如果有连接时进行数据块的读取并且用文件流写入文件中
          if not AThread.Terminated and AThread.Connection.Connected then
          begin
            //读取文件流
            repeat    
              //这里确定每次读取的文件块长度,如果剩余长度比长度长就用自定义的 buff否则用剩余的长度
              if FileSize - Stream.Size > SizeOf(Buff) then
                ReadCount := SizeOf(Buff)
              else
                ReadCount := FileSize - Stream.Size;          AThread.Connection.ReadBuffer(Buff, ReadCount);  //从连接中读取 ReadCount长度的文件块放到缓冲区Buff,中          Stream.WriteBuffer(Buff, ReadCount); //将缓冲区中的内容写进文件流中,这是就是写到文件aFileName中啦          ProgressBar1.Position := Stream.Size; //文件流当前写的大小,值赋给进度条的位置
              Caption := IntToStr(Stream.Size) + '/' + IntToStr(FileSize);  //显示已经传输和实际文件大小的比例          Application.ProcessMessages;  //这句作用是让消息传递动态显示起来,如果没有这句上面的caption是不会显示跳动的        until Stream.Size >= FileSize;  //直到文件大小和原文件大小一致结束循环
            AThread.Connection.WriteLn('OK');  //返回一个信息 OK,让客户端知道你读完了
        //释放一些文件流内存
            Stream.Free;
            Stream := nil;
            //定义成没有人连接,准备接受下一个人的连接
            State := dstNone;
          end;
        end;
      end;{ TThreadData }
    //下面是 TThreadData 的 几个方法和属性的定义,看看就明白了吧
    constructor TThreadData.Create;
    begin
      inherited;
      Stream := nil;
    end;destructor TThreadData.Destroy;
    begin
      if Assigned(Stream) then
        Stream.Free;
      inherited;
    end;procedure TThreadData.SetFileSize(const Value: Integer);
    begin
      FFileSize := Value;
    end;procedure TThreadData.SetState(const Value: TDataState);
    begin
      FState := Value;
    end;procedure TThreadData.SetStream(const Value: TFileStream);
    begin
      FStream := Value;
    end;end.
      

  4.   

    接下来 我把我精简分解出来的代码并测试成功的代码 公布出来请对比一下 上面的客户端代码 看看区别在哪里?帖子末尾我告诉你赫赫--------改写的服务端-------------unit server;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls, Buttons, ComCtrls, IdBaseComponent, IdComponent,
      IdTCPServer;type
      TDataState = (dstNone, dstReceiving);    
      TForm1 = class(TForm)
        IdTCPServer1: TIdTCPServer;
        ProgressBar1: TProgressBar;
        SpeedButton1: TSpeedButton;
        StaticText1: TStaticText;
        StaticText2: TStaticText;
        StaticText3: TStaticText;
        StaticText4: TStaticText;
        SpeedButton2: TSpeedButton;
        procedure SpeedButton1Click(Sender: TObject);
        procedure SpeedButton2Click(Sender: TObject);
        procedure IdTCPServer1Connect(AThread: TIdPeerThread);
        procedure IdTCPServer1Execute(AThread: TIdPeerThread);
      private
        { Private declarations }
      public
        { Public declarations }
      end;var
      Form1: TForm1;
      State:TDataState;implementation{$R *.dfm}procedure TForm1.SpeedButton1Click(Sender: TObject);
    begin
        IdTCPServer1.Active:=true;
        StaticText4.Caption:='服务启动';
    end;procedure TForm1.SpeedButton2Click(Sender: TObject);
    begin
        IdTCPServer1.Active:=false;
        StaticText4.Caption:='服务停止';
    end;procedure TForm1.IdTCPServer1Connect(AThread: TIdPeerThread);
    begin
        State := dstNone;
    end;procedure TForm1.IdTCPServer1Execute(AThread: TIdPeerThread);
    var  //下面定义一些局部变量
      aFileSize : Integer;      //aFileSize用来表示文件大小,整型
      aFileName : String;    //aFileName表示文件名,字串型
      Buff : array[0..1023] of Byte;  // Buff 缓存区大小设置,byte型
      ReadCount : Integer;  //实际每次读取文件块的大小,整型
      Stream : TFileStream;
      begin
      Stream:=nil;
      if State = dstNone then
            begin
              if not AThread.Terminated and AThread.Connection.Connected then
                  begin
                  aFileName := AThread.Connection.ReadLn(#13#10, 100);
                    if aFileName = '' then
                      Exit;
                AThread.Connection.WriteLn;
                AThread.Connection.ReadBuffer(aFileSize, 4);//开始读取文件长度,放进变量aFileSize中
                ProgressBar1.Max := aFileSize;            Stream := TFileStream.Create(aFileName, fmCreate);//创建一个文件流
                State := dstReceiving;
                  end ;
            end;    if not AThread.Terminated and AThread.Connection.Connected then
          begin
            //读取文件流
            repeat          if aFileSize - Stream.Size > SizeOf(Buff) then
                ReadCount := SizeOf(Buff)
              else
                ReadCount := aFileSize - Stream.Size;          AThread.Connection.ReadBuffer(Buff, ReadCount);  //从连接中读取 ReadCount长度的文件块放到缓冲区Buff,中          Stream.WriteBuffer(Buff, ReadCount); //将缓冲区中的内容写进文件流中,这是就是写到文件aFileName中啦          ProgressBar1.Position := Stream.Size; //文件流当前写的大小,值赋给进度条的位置
              Caption := IntToStr(Stream.Size) + '/' + IntToStr(aFileSize);  //显示已经传输和实际文件大小的比例          Application.ProcessMessages;  //这句作用是让消息传递动态显示起来,如果没有这句上面的caption是不会显示跳动的        until Stream.Size >= aFileSize;  //直到文件大小和原文件大小一致结束循环
            AThread.Connection.WriteLn('OK');  //返回一个信息 OK,让客户端知道你读完了
        //释放一些文件流内存    end;      Stream.Free;
          //Stream:=nil;
          //定义成没有人连接,准备接受下一个人的连接
          State:= dstNone;
    end;end.-----服务端代码结束------细心的朋友已经看出区别了吧,我改写后的代码是看着简单直接了,但是却没法多播接受文件,因为是只能接受单播(同一个时刻只能接受一个客户端的连接)的传输。所以说 ,前面的demo是先自定义了一个类 TThreadData 别小看这个类哦,其实这个类定义出来以后传播过来的文件就不会混淆,因为各自是独立的,就是说每个客户端连接过来,都会生成一个这样的类对象,作者目的是什么呢,其实就是为了让各个客户端独立起来,否则,大家都往一个服务端传文件的时候,就会所有的数据块混杂在一起了!那么我为什么要精简他呢,目的只有一个,想测试一下核心代码,因为我还要写一个精简出来的客户端,所以这个服务端就是我特意测试用来写的。-------------------ok!接下来看我精简分解出来的客户端代码
     
    在看代码之前提醒一下,请注意,我这个IdTCPClient组件对象是动态创建的,在Button1Click事件里大家也可以看到动态创建一些对象的方法。这个是我改写的实现 传输文件的 局域网内程序。。用来做数据备份的朋友应该可以使用哦在外网如果是公网IP估计也是可以使用的记住测试的时候 要在客户端目录里 放一个大文件 test.rar  在服务端目录下就会生成一个同样的文件了,这就是传输过来生成的。这个程序只是一个demo用来讲解  idtcpclient  如何 朝 Idtcpserver 传输文件效率还有些问题,就是运行时 感觉本地机器CPU会比较高,就像复制文件一样 赫赫 如何解决这样的问题呢?如果有朋友知道的话 一起探讨一下哦!------------客户端代码--------------------
    unit Unit1;interfaceuses
    Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient,
      StdCtrls;type
      TForm1 = class(TForm)
        Button1: TButton;    procedure Button1Click(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
      end;var
      Form1: TForm1;
      Buf : array[0..1023] of Byte;
      aSize, ReadCount, Tmpint : Integer;
      aStream : TFileStream;
      aIdTCPClient: TIdTCPClient;
      FFileName:string;implementation{$R *.dfm}procedure TForm1.Button1Click(Sender: TObject);
    begin
        FFileName:='test.rar';
        aStream := nil;
        aIdTCPClient := nil;
        try
        aStream := TFileStream.Create(FFileName, fmOpenRead or fmShareDenyWrite);
        aIdTCPClient :=  TIdTCPClient.Create(Application);
        aIdTCPClient.Port := 5432;
        aIdTCPClient.Host := '127.0.0.1';
        aIdTCPClient.Connect(5000);
          //发送文件名
        aIdTCPClient.WriteLn(ExtractFileName(FFileName));
          //等待接受确认
          aIdTCPClient.ReadLn(#13#10, 1000);
          //写文件长度和文件流
          aSize := aStream.Size;
          aIdTCPClient.WriteBuffer(aSize, 4);
              while aStream.Position < aStream.Size do
              begin
                if aStream.Size - aStream.Position >= SizeOf(Buf) then
                    ReadCount := sizeOf(Buf)
                else ReadCount := aStream.Size - aStream.Position;            aStream.ReadBuffer(Buf, ReadCount);
                aIdTCPClient.WriteBuffer(Buf, ReadCount);
              end;
              aIdTCPClient.ReadLn;
              aIdTCPClient.Disconnect;    finally    aIdTCPClient.Disconnect;
        if aStream<>nil then FreeAndNil(aStream);
        if aIdTCPClient<>nil then FreeAndNil(aIdTCPClient);
        end;
    end;end.